《精通Windows API-函数、接口、编程实例》——第4章文件系统

本文详细介绍了WindowsAPI中关于文件系统管理的功能,包括磁盘和驱动器管理、文件和目录管理以及高级文件操作。涵盖了获取逻辑驱动器、驱动器类型、卷信息、文件属性等API函数的使用,以及如何遍历驱动器、操作挂载点和获取磁盘空间信息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

《精通Windows API-函数、接口、编程实例》——第4章文件系统

第4章文件系统

 

 

4.2 磁盘和驱动器管理

 

 

 

 

文件系统的基本概念:
包括磁盘分区,卷,目录,文件对象,文件句柄,文件映射
1.磁盘分区:
物理磁盘,逻辑磁盘
2.卷:
也称逻辑驱动器,是NTFS,FAT32等文件系统组织结构的最高层.
卷是存储设备(硬盘)上由文件系统管理的一块区域,在逻辑上相互隔离的存储单元.

windows命名规则:
主文件名+扩展名
windows中文件系统的长度被限制为260个字符.
这260个字符包括卷标,路径,主文件名和扩展名,分隔符

在DOS下的保留设备名不能做文件名或主文件名.如CON,PRN,AUX,NUL,COM1.....

=================================================================

磁盘和驱动器管理API
GetLogicalDrivers       获取主机中所有的逻辑驱动器,以Bit Map的形式返回.
GetLogicalDriverString    获取主机中所有的逻辑驱动器,以驱动器根路径字符串返回.
FindFirstVolume     查找主机中的第一个驱动器,返回查找句柄.
FindNextVolume      根据FindFirstVolume返回句柄,查找主机中后继的逻辑驱动器
FindVolumeClose     关闭驱动器查找句柄
GetDriveType      获取驱动器类型
GetVolumeInformation    获取逻辑驱动器信息
FindFirstVolumeMountPoint 查找指定卷的第一个挂载点,返回查找句柄
FindNextVolumeMountPoint 根据FindFirstVolumeMountPoint返回的句柄,查找卷的后继挂载点.
FindVolumeMountPointClose 关闭挂载点查找句柄
GetVolumeNameForVolumeMountPoint 根据指定挂载点获取相应的卷设备名
SetVolumeMountPoint         将指定卷挂载到指定挂载点处
GetDiskFreeSpace            获取磁盘空间信息,包括每簇的扇区数,每扇区的字节数,簇数量,空闲的簇数量
GetDiskFreeSpaceEx          获取用户可用的空闲空间的字节数,磁盘总容量的字节数

文件和目录管理API
DeleteFile                  删除参数所指定文件
CopyFile                    复制指定文件为一个新文件
MoveFile                    将指定文件或目录移动到指定位置
CreateFile                  新建或打开一个文件,获取文件句柄
ReadFile                    读取由文件句柄指定文件的内容
WriteFile                   向由文件句柄指定的文件中写入内容
GetFileSize                 获取文件大小,返回DWORD中;大小超出DWORD最大值时可指定高32位的DWORD联合存储
GetFileSizeEx               获取文件大小,存储到一个64位的大整数联合体中.
CreateDirectory             创建一个目录
GetCurrentDirectory         获取当前程序所在目录
SetCurrentDirectory         设置当前程序所在目录
GetModuleFileName           获取当前模块全路径
FindFirstFile               查找指定目录下第一个文件句柄或目录,获得查找句柄
FindNextFile                根据FindFirstFile获得的句柄,循环查找文件或目录
GetFileAttributes           获取指定文件目录属性,返回一个DWORD值
GetFileAttributesEx         获取文件或目录属性,存储在WIN32_FILE_ATTRIBUTE_DATA结构体中
SetFileAttributes           将文件属性设定为指定值
FileTimeToLocalFileTime     将文件时间转换为本地时间
FileTimeToSystemTime        将文件转换为系统时间,SYSTEMTIME格式便于显示

高级文件操作
CreateFileMapping           创建文件的映射对象
MapViewOfFile               创建视图,将创建的文件映射对象映射到当前进程的地址空间中
FlushViewOfFile             将视图中的数据都写入磁盘,对视图的操作都会反映到磁盘上的文件中
OpenFileMapping             打开已经存在的命名的文件映射对象
UnmapViewOfFile             取消文件映射
GetMappedFileName           从映射对象获取被映射文件的文件设备名
QueryDosDevice              获取MS-DOS设备名

=================================================================

2 磁盘和驱动器管理

◇使用两种方法来遍历驱动器并获取驱动器属性。
◇使用API操作驱动器挂载点。
◇判断光驱中是否有光盘。
◇获取磁盘剩余空间、扇区信息等。

 



 

4.2.1 遍历卷并获取属性

用到的API函数:

 

(1) GetLogicalDrives。
获取主机中所有的逻辑驱动器,以BitMap的形式返回,其函数原型如下:

(2) GetLogicalDriverStrings。
获取主机中所有驱动器,以驱动器根路径字符串返回,其函数原型如下:

(3)FindFirstVolume。
查找主机中的第一个驱动器,返回驱动器设备名,其函数原型如下:

(4)FindNextVolume
查找主机中后继的逻辑驱动器,其函数原型如下:

(5)FindVo1umeClose。
\关闭FindFirstVolume打开的卷遍历句柄,其函数原型如下:

(6) GetDriveType。
获取驱动器类型,其函数原型如下:

(7) GetVolumeInformation。
获取逻辑驱动器信息,其函数原型如下:

    

 

[cpp] view plaincopyprint?

  1. /* ************************************ 
  2.  *《精通Windows API》  
  3.  * 示例代码 
  4.  * GetVolumeInfo.c 
  5.  * 4.2.1    遍历驱动器并获取驱动器属性 
  6.  **************************************/  
  7.   
  8. /* 头文件 */  
  9. #include <windows.h>   
  10. #include <stdlib.h>   
  11. #include <stdio.h>   
  12. #include <string.h>   
  13. /* 预定义 */  
  14. #define BUFSIZE 1024   
  15. /* 函数申明 */  
  16. BOOL GetDirverInfo(LPSTR szDrive);  
  17.   
  18. /* ************************************ 
  19.  * 功能   应用程序主函数,遍历驱动器并调用 
  20.  *          GetDirverInfo 获取驱动器属性 
  21.  **************************************/  
  22. void main(void)  
  23. {  
  24.     CHAR szLogicalDriveStrings[BUFSIZE];  
  25.     PCHAR szDrive;  
  26.   
  27.     ZeroMemory(szLogicalDriveStrings,BUFSIZE);  
  28.     // 获取逻辑驱动器卷标名   
  29.     GetLogicalDriveStrings(BUFSIZE - 1,szLogicalDriveStrings);    
  30.     szDrive = (PCHAR)szLogicalDriveStrings;  
  31.     // 循环处理每个卷   
  32.     do  
  33.     {  
  34.         if(!GetDirverInfo(szDrive))  
  35.         {  
  36.             printf("/nGet Volume Information Error: %d", GetLastError());  
  37.         }  
  38.       
  39.       
  40.           
  41.     szDrive += (lstrlen(szDrive)+1);  
  42.     }  
  43.     while(*szDrive!='/x00');  
  44. }  
  45.   
  46. /* ************************************ 
  47.  * BOOL GetDirverInfo(LPSTR szDrive) 
  48.  * 功能   获取驱动器的属性 
  49.  * 参数   LPSTR szDrive 
  50.  *  指明要获取属性的驱动器的根路径 如 C:/ 
  51.  * 返回值 BOOL 是否成功 
  52.  **************************************/  
  53. BOOL GetDirverInfo(LPSTR szDrive)  
  54. {     
  55.   
  56.   
  57.     UINT uDriveType;  
  58.     DWORD dwVolumeSerialNumber;  
  59.     DWORD dwMaximumComponentLength;  
  60.     DWORD dwFileSystemFlags;  
  61.     TCHAR szFileSystemNameBuffer[BUFSIZE];  
  62. printf("/n%s/n",szDrive);  
  63.       
  64.     uDriveType = GetDriveType(szDrive);  
  65.     // 判断类型   
  66.     switch(uDriveType)  
  67.     {  
  68.     case DRIVE_UNKNOWN:  
  69.         printf("The drive type cannot be determined. 未知的磁盘类型  ");  
  70.         break;  
  71.     case DRIVE_NO_ROOT_DIR:  
  72.         printf("The root path is invalid, for example, no volume is mounted at the path. 说明lpRootPathName是无效的  ");  
  73.         break;  
  74.     case DRIVE_REMOVABLE:  
  75.         printf("The drive is a type that has removable media, for example, a floppy drive or removable hard disk. 可移动磁盘 ");  
  76.         break;  
  77.     case DRIVE_FIXED:  
  78.         printf("The drive is a type that cannot be removed, for example, a fixed hard drive. 固定磁盘 ");  
  79.         break;  
  80.     case DRIVE_REMOTE:  
  81.         printf("The drive is a remote (network) drive. 网络磁盘  ");  
  82.         break;  
  83.     case DRIVE_CDROM:  
  84.         printf("The drive is a CD-ROM drive. 光驱 ");  
  85.         break;  
  86.     case DRIVE_RAMDISK:  
  87.         printf("The drive is a RAM disk. ");  
  88.         break;  
  89.     default:  
  90.         break;  
  91.     }  
  92.     if (!GetVolumeInformation(  
  93.         szDrive, NULL, 0,  
  94.         &dwVolumeSerialNumber,  
  95.         &dwMaximumComponentLength,  
  96.         &dwFileSystemFlags,  
  97.         szFileSystemNameBuffer,  
  98.         BUFSIZE  
  99.         ))  
  100.     {  
  101.         return FALSE;  
  102.     }  
  103.     printf ("/nVolume Serial Number is 存储驱动器序列号%u",dwVolumeSerialNumber);  
  104.     printf ("/nMaximum Component Length is 文件系统所支持的文件组成部分的最大值%u",dwMaximumComponentLength);  
  105.     printf ("/nSystem Type is文件系统类 %s/n",szFileSystemNameBuffer);  
  106.   
  107.     if(dwFileSystemFlags & FILE_SUPPORTS_REPARSE_POINTS)  
  108.     {  
  109.         printf ("The file system does not support volume mount points./n");  
  110.     }  
  111.     if(dwFileSystemFlags & FILE_VOLUME_QUOTAS)  
  112.     {  
  113.         printf ("The file system supports disk quotas./n");  
  114.     }  
  115.     if(dwFileSystemFlags & FILE_CASE_SENSITIVE_SEARCH)  
  116.     {  
  117.         printf ("The file system supports case-sensitive file names./n");  
  118.     }  
  119.     //you can use these value to get more informaion   
  120.     //   
  121.     //FILE_CASE_PRESERVED_NAMES   
  122.     //FILE_CASE_SENSITIVE_SEARCH   
  123.     //FILE_FILE_COMPRESSION   
  124.     //FILE_NAMED_STREAMS   
  125.     //FILE_PERSISTENT_ACLS   
  126.     //FILE_READ_ONLY_VOLUME   
  127.     //FILE_SUPPORTS_ENCRYPTION   
  128.     //FILE_SUPPORTS_OBJECT_IDS   
  129.     //FILE_SUPPORTS_REPARSE_POINTS   
  130.     //FILE_SUPPORTS_SPARSE_FILES   
  131.     //FILE_UNICODE_ON_DISK   
  132.     //FILE_VOLUME_IS_COMPRESSED   
  133.     //FILE_VOLUME_QUOTAS   
  134.     printf(".../n");  
  135.     return TRUE;  
  136. }  

  

 

 


 


 4.2.2 操作驱动器挂载点

一般可以用FindFirstVolumeMountPoint系列的API来找到一个卷的所有挂载点;用
GetVolumeNameForVolumeMountPoint来获取指定挂载点所指向的卷名,卷名形式为"//?/Volume{GUID}/”;用SetVolumeMountPoint来设置新的挂载点。
通过系统的磁盘管理功能可以设置卷的挂载点,如图4-2所示。


◇“我的电脑”图标右键菜单中选择“管理”。
◇弹出“计算机管理”窗口,选择“磁盘管理”。
◇选中需要挂载的卷,在右键菜单中选择“更改驱动 器名和路径”。
◇在弹出的对话框中单击“添加”按钮,选择“装入 以下空白NTFS文件夹”。
◇选择需要将卷挂载入的文件夹(空白),单击“确定”按钮。
◇卷就被装入文件夹中,之后就可以和访问文件夹一个访问这个卷了,如图4-3和4-4

 

(1)FindFirstVolumeMountPoint.
获取指定卷的第一个挂载点,函数原型如下:
以用GetLastError()函数获取更详细的错误信息。
(2) FindNextVolumeMountPoint
查找指定卷的后继挂载点,函数原型如下:

(3)FindVolumeMountPointClose.
关闭FindVolumeMountPointClose打开的卷句柄,其函数原型如下:
◇参数
hFindVolumeMountPoint:要关闭的挂载点查找句柄。
◇返回值
(4)GetVolumeNameForVolumeMountPoint。
根据指定的挂载点获取相应的卷设备名,函数原型如下:

(5)SetVolumeMountPc
将指定卷挂载到指定挂载点处,函数原型如下:

[cpp] view plaincopyprint?

  1. /* ************************************ 
  2.  *《Windows应用程序开发》  
  3.  * 示例代码 
  4.  * mount.c 
  5.  * 4.2.2    卷挂载点操作 
  6.  **************************************/  
  7. /* 预编译声明 */  
  8. #define _WIN32_WINNT 0x0501   
  9. #include <windows.h>   
  10. #include <stdio.h>   
  11. #include <tchar.h>   
  12. #define BUFSIZE            MAX_PATH   
  13. #define FILESYSNAMEBUFSIZE MAX_PATH   
  14.   
  15. /* ************************************ 
  16.  * ProcessVolumeMountPoint 
  17.  * 功能   列举挂载点 
  18.  **************************************/  
  19. BOOL ProcessVolumeMountPoint (HANDLE hPt,  
  20.                               TCHAR *PtBuf, DWORD dwPtBufSize,  
  21.                               TCHAR *Buf)  
  22. {  
  23.     BOOL bFlag;                 // 结果   
  24.     TCHAR Path[BUFSIZE];    // 全路径   
  25.     TCHAR Target[BUFSIZE];      // 挂载点设备   
  26.   
  27.     printf ("/tVolume mount point found is /"%s/"/n", PtBuf);  
  28.   
  29.     lstrcpy (Path, Buf);  
  30.     lstrcat (Path, PtBuf);  
  31.   
  32.     bFlag = GetVolumeNameForVolumeMountPoint(  
  33.         Path,  Target,  BUFSIZE     );  
  34.   
  35.     if (!bFlag)  
  36.         printf ("/tAttempt to get volume name for %s failed./n", Path);  
  37.     else   
  38.         printf ("/tTarget of the volume mount point is %s./n", Target);  
  39.   
  40.     bFlag = FindNextVolumeMountPoint(  
  41.         hPt,  PtBuf,  dwPtBufSize );  
  42.     return (bFlag);  
  43. }  
  44. /* ************************************ 
  45.  * ProcessVolume 
  46.  * 功能   判断卷类型,列举挂载点 
  47.  **************************************/  
  48. BOOL ProcessVolume (HANDLE hVol, TCHAR *Buf, DWORD iBufSize)  
  49. {  
  50.     BOOL bFlag;           // 返回标志   
  51.     HANDLE hPt;           // 卷句柄   
  52.     TCHAR PtBuf[BUFSIZE]; // 挂载点路径   
  53.     DWORD dwSysFlags;     // 文件系统标记   
  54.     TCHAR FileSysNameBuf[FILESYSNAMEBUFSIZE];  
  55.   
  56.     printf ("Volume found is /"%s/"./n", Buf);  
  57.   
  58.     // 是否NTFS   
  59.     GetVolumeInformation( Buf, NULL, 0, NULL, NULL,  
  60.         &dwSysFlags, FileSysNameBuf,   
  61.         FILESYSNAMEBUFSIZE);  
  62.   
  63.     if (! (dwSysFlags & FILE_SUPPORTS_REPARSE_POINTS))   
  64.     {  
  65.         printf ("/tThis file system does not support volume mount points./n");  
  66.     }   
  67.     else   
  68.     {  
  69.         // 本卷中的挂载点   
  70.         hPt = FindFirstVolumeMountPoint(  
  71.             Buf, // 卷的跟跟踪   
  72.             PtBuf, // 挂载点路径   
  73.             BUFSIZE   
  74.             );  
  75.   
  76.         if (hPt == INVALID_HANDLE_VALUE)  
  77.         {  
  78.             printf ("/tNo volume mount points found!/n");  
  79.         }   
  80.         else   
  81.         {  
  82.             // 处理挂载点   
  83.             bFlag = ProcessVolumeMountPoint (hPt,   
  84.                 PtBuf,   
  85.                 BUFSIZE,   
  86.                 Buf);  
  87.             // 循环   
  88.             while (bFlag)   
  89.                 bFlag =   
  90.                 ProcessVolumeMountPoint (hPt, PtBuf, BUFSIZE, Buf);  
  91.             // 结束   
  92.             FindVolumeMountPointClose(hPt);  
  93.         }  
  94.     }  
  95.   
  96.     // 下一个   
  97.     bFlag = FindNextVolume(  
  98.         hVol, Buf,  iBufSize);  
  99.   
  100.     return (bFlag);   
  101. }  
  102. /* ************************************ 
  103.  * int GetMountPoint(void) 
  104.  * 功能   获取挂载点 
  105.  **************************************/  
  106. int GetMountPoint(void)  
  107. {  
  108.     TCHAR buf[BUFSIZE];     // 卷标识符   
  109.     HANDLE hVol;                    // 卷句柄   
  110.     BOOL bFlag;                 // 结果标志   
  111.   
  112.     printf("Volume mount points info of this computer:/n/n");  
  113.     // 打开卷   
  114.     hVol = FindFirstVolume (buf, BUFSIZE );  
  115.     if (hVol == INVALID_HANDLE_VALUE)  
  116.     {  
  117.         printf ("No volumes found!/n");  
  118.         return (-1);  
  119.     }  
  120.   
  121.     bFlag = ProcessVolume (hVol, buf, BUFSIZE);  
  122.     while (bFlag)   
  123.     {  
  124.         bFlag = ProcessVolume (hVol, buf, BUFSIZE);  
  125.     }  
  126.   
  127.     bFlag = FindVolumeClose(    hVol );  
  128.     return (bFlag);  
  129. }  
  130.   
  131. /* ************************************ 
  132.  * void Usage (PCHAR argv) 
  133.  * 功能   使用方法 
  134.  **************************************/  
  135. void Usage (PCHAR argv)  
  136. {  
  137.     printf( "/n/n/t%s, mount a volume at a mount point./n", argv );  
  138.     printf( "/tFor example, /"mount D://mnt//drives// E:///"/n" );   
  139. }  
  140.   
  141. /* ************************************ 
  142.  *  main 
  143.  * 功能   入口函数 
  144.  **************************************/  
  145. int main( int argc, PCHAR argv[] )  
  146. {  
  147.     BOOL bFlag;  
  148.     CHAR Buf[BUFSIZE];       
  149.   
  150.     if( argc != 3 )   
  151.     {  
  152.         GetMountPoint();  
  153.         Usage( argv[0] );  
  154.         return( -1 );  
  155.     }  
  156.   
  157.     bFlag = GetVolumeNameForVolumeMountPoint(  
  158.         argv[2],        // 输入挂载点或目录   
  159.         Buf,                // 输出卷名   
  160.         BUFSIZE  
  161.         );  
  162.   
  163.     if (bFlag != TRUE)   
  164.     {  
  165.         printf( "Retrieving volume name for %s failed./n", argv[2] );  
  166.         return (-2);  
  167.     }  
  168.   
  169.     printf( "Volume name of %s is %s/n", argv[2], Buf );  
  170.     bFlag = SetVolumeMountPoint(  
  171.         argv[1],    // 挂载点   
  172.         Buf         // 需要挂载的卷   
  173.         );  
  174.   
  175.     if (!bFlag)  
  176.     {  
  177.         printf ("Attempt to mount %s at %s failed. error code is/n",   
  178.             argv[2], argv[1], GetLastError());  
  179.     }  
  180.   
  181.     return (bFlag);  
  182. }  

 

 


 


4.2.3 判断光驱中是否有光盘

 判断光驱中是否有光盘,仍然可以使用在4.2.1小节介绍的GetDriveType和GetVolumeInformation函数实现。首先使用驱动器根路径作为GetDriveType和参数,如果返回值是DRIVE_CDROM,则说明此驱动器为光驱。然后使用GetVolumeInformation获取信息,如果成功,则说明存光盘已经放入。调用完成后GetVolumeInformation函数的第7个参数LPTSTR lpFileSystemNameBuffer存储的是文件系统的类别字符串,光盘一般是CDFS。如果调用GetVolumeInformation时返回FALSE,并且GetLastError返回21,则说明驱动器中未放入光盘。

1.关键API
(1)GetDiskType与GetVolumeInformation。
这两个API已经在4.2.1小节介绍过,这里不再赘述。
(2)GetLastError。
获取在执行中本线程最近的一次错误。本函数是很多系统API返回执行错误原因的方法。可能使用SetLastError函数设置本线程的Last-Error值。GetLastError函数原型如下:

[cpp] view plaincopyprint?

  1.  * 4.2.3    判断光驱中是否有光盘  
  2.  **************************************/  
  3. /* 头文件 */  
  4. #include <windows.h>   
  5. #include <stdio.h>   
  6. #include <tchar.h>   
  7. /* 预定义 */  
  8. #define BUFSIZE            512   
  9.   
  10. /* ************************************ 
  11.  * int main( int argc, PCHAR argv[] ) 
  12.  * 功能   应用程序主函数,根据输入的驱动器 
  13.  *      根路径参数判断是否为光驱,是否放 
  14.  *      入光盘。 
  15.  * 参数   驱动器根路径,比如“D:/”。 
  16.  **************************************/  
  17.   
  18. int main( int argc, PCHAR argv[] )  
  19. {  
  20.     //存储文件系统类别名   
  21.     CHAR szFileSystemNameBuffer[BUFSIZE];  
  22.     DWORD dwLastError;  
  23.     DWORD dwFileSystemFlags;  
  24.   
  25.     //判断是否输入运行时参数   
  26.     if( argc != 2 )   
  27.     {  
  28.         printf("请输入驱动器的根路径,比如: /"D:///"/n");   
  29.         return( -1 );  
  30.     }  
  31.       
  32.     //判断输入的驱动器是否为CD/DVD ROM   
  33.     if(GetDriveType(argv[1])!=DRIVE_CDROM)  
  34.     {  
  35.         printf("驱动器 %s 不是 CD/DVD ROM。/n",argv[1]);  
  36.         return( -1 );  
  37.     }  
  38.       
  39.     //获取卷信息   
  40.     if (!GetVolumeInformation(  
  41.         argv[1], NULL, 0,  
  42.         NULL,NULL,  
  43.         &dwFileSystemFlags,  
  44.         szFileSystemNameBuffer,  
  45.         BUFSIZE  
  46.         ))  
  47.     {  
  48.         dwLastError = GetLastError();  
  49.         if(dwLastError == 21)  
  50.         {  
  51.             printf("设备未就绪,请放入光盘!/n");  
  52.             return 0;  
  53.         }  
  54.         else  
  55.         {  
  56.             printf("GetVolumeInformation 错误 %d/n",dwLastError);  
  57.             return 0;  
  58.         }  
  59.     }  
  60.     printf ("光盘已经放入,文件系统类别 %s。/n",szFileSystemNameBuffer);  
  61.     return 0;  
  62. }  


4.2.4 获取磁盘分区的总容量、空闲容量、簇、扇区信息

获取磁盘分区的总容量和空闲空间的容量可以使用GetDiskFreeSpace函数或GetDiskFree SpaceEx函数。GetDiskFreeSpace使用DWORD类型作为输出参数,由于DWOR长度为32位,最大只能表示4GB,而一般的磁盘分区大小都大于4GB,所以,GetDiskFreeSpace并不直接返回磁盘的总容量和空闲空间的容量,而是使用总簇数、空闲的簇数、每簇的扇区数、每扇区的字节数来表示。用户在编程时,可以使用它们的乘积来获得最终结果。而GetDiskFreeSpaceEx使用ULARGE_INTEGER (DWORD64)类型的数据来存储磁盘空间总空间和剩余空间,所以可以直接获得结果。DWORD64可以表示约16777216TB的数据量(DWORD64最大可表示2Byte,lTB=2Byte,

(2)GetDiskFreeSpacEX。
获取驱动器根路径作为输入,获取用户可用的空闲空间的字节数、空闲空间的字节数、磁盘总容量的字节数,其函数原型如下:

2.关键数据结构
GetDiskFreeSpaceEx函数使用到了数据结构ULARGE_INTEGER,数据类型PULARGE
INTEGER是指向它的指针。ULARGE__ INTEGER的定义如下,此数据结构使用两个DWORD来表
示64位数据。低位存储于前,高位存储于后,与DWORD64的存储形式是一致的,所以可以直接强制类型转换为DOWRD64类型。也可以直接使用QuadPart成员,QuadPart成员是ULONGLONG形数据结构,在一般32位主机上,与DWORD64具有同样的长度。

[cpp] view plaincopyprint?

  1. /* ************************************ 
  2.  *《精通Windows API》  
  3.  * 示例代码 
  4.  * diskspace.c 
  5.  * 4.2.4    获取磁盘空间信息 
  6.  **************************************/  
  7.   
  8. /* 头文件 */  
  • #include <windows.h>   
  • #include <stdio.h>   
  •   
  • /* ************************************ 
  •  * BOOL GetDiskSpaceInfo(LPCSTR pszDrive 
  •  * 功能   根据输入的驱动器,获取磁盘总容量 
  •  *          空闲空间、簇数量等磁盘信息 
  •  * 参数   驱动器根路径,比如“D:/”。 
  •  **************************************/  
  • BOOL GetDiskSpaceInfo(LPCSTR pszDrive)  
  • {  
  •     DWORD64 qwFreeBytesToCaller, qwTotalBytes, qwFreeBytes;  
  •     DWORD dwSectPerClust, dwBytesPerSect, dwFreeClusters,  dwTotalClusters;  
  •     BOOL bResult;  
  •       
  •     //使用GetDiskFreeSpaceEx获取磁盘信息并打印结果   
  •     bResult = GetDiskFreeSpaceEx (pszDrive,  
  •         (PULARGE_INTEGER)&qwFreeBytesToCaller,  
  •         (PULARGE_INTEGER)&qwTotalBytes,  
  •         (PULARGE_INTEGER)&qwFreeBytes);  
  •   
  •     if(bResult)   
  •     {  
  •         printf("使用GetDiskFreeSpaceEx获取磁盘空间信息/n");  
  •         printf("可获得的空闲空间(字节): /t%I64d/n", qwFreeBytesToCaller);  
  •         printf("空闲空间(字节): /t/t%I64d/n", qwFreeBytes);  
  •         printf("磁盘总容量(字节): /t/t%I64d/n", qwTotalBytes);  
  •     }  
  •   
  •     //使用GetDiskFreeSpace获取磁盘信息并打印结果   
  •     bResult = GetDiskFreeSpace (pszDrive,   
  •         &dwSectPerClust,   
  •         &dwBytesPerSect,  
  •         &dwFreeClusters,   
  •         &dwTotalClusters);  
  •   
  •     if(bResult)   
  •     {  
  •         printf("/n使用GetDiskFreeSpace获取磁盘空间信息/n");  
  •         printf("空闲的簇数量 : /t/t/t%d/n",dwFreeClusters);  
  •         printf("总簇数量 : /t/t/t%d/n",dwTotalClusters);  
  •         printf("每簇的扇区数量 : /t/t%d/n",dwSectPerClust);  
  •         printf("每扇区的容量(字节): /t/t%d/n",dwBytesPerSect);  
  •         printf("空闲空间(字节): /t/t%I64d/n",   
  •             (DWORD64)dwFreeClusters*  
  •             (DWORD64)dwSectPerClust*(DWORD64)dwBytesPerSect);  
  •         printf("磁盘总容量(字节): /t/t%I64d",  
  •             (DWORD64)dwTotalClusters*  
  •             (DWORD64)dwSectPerClust*(DWORD64)dwBytesPerSect);  
  •     }  
  •     return bResult;  
  • }  
  •   
  • /* ************************************ 
  •  * int main( int argc, PCHAR argv[] ) 
  •  * 功能   应用程序主函数,根据输入参数 
  •  *          调用GetDiskSpaceInfo函数获取 
  •  *          磁盘空间信息 
  •  * 参数   驱动器根路径,比如“D:/”。 
  •  **************************************/  
  • int main(int argc, PCHAR argv[])  
  • {  
  •     GetDiskSpaceInfo (argv[1]);  
  • }  

 

 

 



 

4.3 文件和目录管理


文件和目录管理是Windows系统编程最为基本的内容,几乎所有的应用程序都会使用到文件和目录的操作。本节将向读者演示如何创建目录、遍历目录、创建文件、打开文件、读写文件、移动复制删除文件等。本节通过以下多个实例来讲解Windows API对文件和目录的管理。
◇删除、复制、重命名、移动文件。
◇创建、打开、读写文件。
◇创建、打开目录。
◇获取当前目录、获取程序所在的目录、获取模块路径。
◇查找文件、遍历目录下的文件和子目录。
◇递归遍历目录树。

◇获取、设置文件属性和时间。


4.3.1 删除、复制、重命名、移动文件


Windows系统为文件的删除、复制、重命名或移动文件提供了相应的API函数。删除文件使用DeleteFile函数;复制文件使用CopyFile函数;重命名文件和移动文件实际是一个操作,使用MoveFile函数。这几个函数的使用都非常简单,下面分别介绍。
1.关键API
(1) DeleteFile。

DeleteFile的功能是删除文件。以文件路径作为输入,指向需要删除的文件。文件路径可以是类似于“c:/files/delete.txt”的绝对路径,也可以是类似于“./delete.txt”的相对路径,二相对于可执行文件所在的路径。

(2) CopyFile。
CopyFile的功能是复制文件。通过参数输入复制文件和源路径和目的路径,路径可以是绝对路径也可以是相对路径,还可以通过参数指明如果目的路径已经存在文件,是否覆盖。可以使用CopyFileEx函数进行更为高级的操作,比如在复制进行过程中取消复制等。CopyFileEx可以指定
一个回调函数来处理文件复制中所可能发生的各种情况。

3) MoveFile。
MoveFile的功能是移动、重命名文件和目录。通过参数输入源路径和目的路径,路径可以是绝对路径也可以是相对路径,如果目的路径的文件或目录已经存在,则返回失败。可以使用MoveFileEx函数来指定更多的选项,如果已经存在是否替换等。还可以使用MoveFileWithProgress指定一个回调函数来处理文件移动中所可能发生的各种情况。函数原型如下:

(4) CopyFileEx、MoveFileEx以及MoveFileWithProgreSS.
这3个API函数功能更丰富,但是限于篇幅这里不再做详细介绍,读者可以使用SDK文档学习它们的使用方法。

 

 

[cpp] view plaincopyprint?

  1. /* ************************************ 
  2. *《精通Windows API》  
  3. * 示例代码 
  4. * wr.c 
  5. * 4.3.2 创建、打开、读写文件,获取文件大小 
  6. **************************************/  
  7.   
  8. /* 头文件 */  
  • #include <windows.h>   
  • #include <stdio.h>   
  •   
  • /* ************************************ 
  • * DWORD ReadFileContent(LPSTR szFilePath) 
  • * 功能    获取文件大小 
  • *       读取文件内容,并以16进制的形式打印出来 
  • * 参数    LPSTR szFilePath 
  • *       文件路径 
  • **************************************/  
  • DWORD ReadFileContent(LPSTR szFilePath)  
  • {  
  •     //文件大小   
  •     HANDLE hFileRead;  
  •     //保存文件大小   
  •     LARGE_INTEGER liFileSize;  
  •     //成功读取的文件数据大小   
  •     DWORD dwReadedSize;  
  •     //累加计算已经读取数据的大小   
  •     LONGLONG liTotalRead = 0;  
  •     //文件数据缓存   
  •     BYTE lpFileDataBuffer[32];  
  •   
  •     //打开已经存在的文件,读取内容。      
  •     hFileRead = CreateFile(szFilePath,// 要打开的文件名   
  •         GENERIC_READ,              // 以读方式打开   
  •         FILE_SHARE_READ,           // 可共享读   
  •         NULL,                      // 默认安全设置   
  •         OPEN_EXISTING,             // 只打开已经存在的文件   
  •         FILE_ATTRIBUTE_NORMAL,     // 常规文件属性   
  •         NULL);                     // 无模板   
  •   
  •     //打开文件是否成功。   
  •     if(hFileRead==INVALID_HANDLE_VALUE)  
  •     {  
  •         printf("打开文件失败:%d",GetLastError());  
  •     }  
  •   
  •     if(!GetFileSizeEx(hFileRead,&liFileSize))  
  •     {  
  •         printf("获取文件大小失败:%d",GetLastError());  
  •     }  
  •     else  
  •     {  
  •         printf("文件大小为:%d/n",liFileSize.QuadPart);  
  •     }  
  •   
  •     //循环读取并打印文件内容   
  •     while(TRUE)  
  •     {  
  •         DWORD i;  
  •   
  •         if(!ReadFile(hFileRead, //读文件的句柄   
  •             lpFileDataBuffer,   //存储读取的文件内容   
  •             32,                 //读的大小(字节)   
  •             &dwReadedSize,      //实际读取的大小   
  •             NULL))              //不使用Overlapped   
  •         {  
  •             printf("读文件错误:%d/n",GetLastError());  
  •             break;  
  •         }  
  •         printf("读取了%d字节,文件内容是:",dwReadedSize);  
  •           
  •         for(i=0; i<dwReadedSize; i++)  
  •         {  
  •             printf("0x%x ",lpFileDataBuffer[i]);  
  •         }  
  •         printf("/n");  
  •         liTotalRead += dwReadedSize;  
  •         if(liTotalRead == liFileSize.QuadPart)  
  •         {  
  •             printf("读文件结束/n");  
  •             break;  
  •         }  
  •     }  
  •     CloseHandle(hFileRead);  
  •     return 0;  
  • }  
  •   
  • /* ************************************ 
  • *  SaveDataToFile 
  • * 功能    将数据存储到文件末尾 
  • * 参数    LPSTR szFilePath    文件路径 
  • *       LPVOID lpData       需存储的数据 
  • *       DWORD dwDataSize    数据大小(字节) 
  • **************************************/  
  • DWORD SaveDataToFile(  
  •                      LPSTR szFilePath,  
  •                      LPVOID lpData,  
  •                      DWORD dwDataSize)  
  • {  
  •     //文件句柄   
  •     HANDLE hFileWrite;  
  •     //成功写入的数据大小   
  •     DWORD dwWritedDateSize;  
  •   
  •     //打开已经存在的文件,读取内容。      
  •     hFileWrite = CreateFile(szFilePath, // 要打开的文件名   
  •         GENERIC_WRITE,          // 以写方式打开   
  •         0,                      // 可共享读   
  •         NULL,                   // 默认安全设置   
  •         OPEN_ALWAYS,            // 打开已经存在的文件,没用则创建   
  •         FILE_ATTRIBUTE_NORMAL,  // 常规文件属性   
  •         NULL);                  // 无模板   
  •       
  •     //判断是否打开成功   
  •     if(hFileWrite==INVALID_HANDLE_VALUE)  
  •     {  
  •         printf("打开文件失败:%d/n",GetLastError());  
  •     }  
  •   
  •     //设置文件指针到文件尾   
  •     SetFilePointer(hFileWrite,0,0,FILE_END);  
  •   
  •     //将数据写入文件   
  •     if(!WriteFile(hFileWrite,lpData,dwDataSize,&dwWritedDateSize,NULL))  
  •     {  
  •         printf("写文件失败:%d/n",GetLastError());  
  •     }  
  •     else  
  •     {  
  •         printf("写文件成功,写入%d字节。/n",dwWritedDateSize);  
  •     }  
  •     CloseHandle(hFileWrite);  
  •     return 0;  
  • }  
  •   
  • /* ************************************ 
  • * int main(void) 
  • * 功能    演示使用SaveDataToFile和ReadFileContent函数 
  • **************************************/  
  • int main(void)  
  • {  
  •     LPSTR szFileData = "这是一个例子";  
  •     SaveDataToFile("C://show.txt",szFileData,lstrlen(szFileData));  
  •     ReadFileContent("C://show.txt");  
  •     return 0;  
  • }  

 

 


 

 


 

4.3.2 创建、打开、读写文件,获取文件大小

在Windows系统中,创建和打开文件都是使用API函数CreateFile,CreateFile通过指定不同的参数来表示是新建一个文件,打开已经存在的文件,还是重新建立文件等。读写文件最为直接的方式是使用ReadFile和WriteFile函数,也可以使用文件镜像,获取文件大小一般使用GetFileSize函数,也可以使用GetFileAttributesEx等函数(在4.3.7节介绍)。读写文件、获取文件大小之前都需要使用CreateFile创建或打开的文件,获得文件句柄。
在文件操作中,文件句柄是一个关键的概念。文件句柄惟一标识了一个文件,ReadFile、
WriteFile、GetFileSize等函数是使用文件句柄作为参数来表示,用户需要读、写、获取大小的文件是哪一个文件。在对文件进行操作前,都必须要使用CreateFile获得文件句柄。

 

1.关键API
(1)CreateFile
CreateFile是文件操作中最主要的一个函数。几乎所有的文件操作都需要使用到文件句柄。而CreateFile函数为这些操作建立文件句柄。CreateFile函数定义如下:

(2)ReadFile。

ReadFile动能是从文件中读出数据。需要使用CreateFile所返回的文件句柄。函数原型如下:

(3)WriteFile。
WriteFile函数的功能是将数据写入到文件中,写入到文件指针所在的位置,写入操作完成后,文件指针会移动到写入的数据之后,函数原型如下:

(4)GetFileSize、GetFileSizeEX.
GetFileSize、GetFileSizeEX的功能是一致的,都是获取文件大小,函数原型分别如下。

[cpp] view plaincopyprint?

  1. /* ************************************ 
  2.  *《精通Windows API》  
  3.  * 示例代码 
  4.  * files.c 
  5.  * 4.3.1    删除、复制、重命名、移动文件 
  6.  **************************************/  
  7.   
  8. /* 头文件 */  
  9. #include <windows.h>   
  10. #include <stdio.h>   
  11.   
  12. /* ************************************ 
  13.  * int main( int argc, PCHAR argv[] ) 
  14.  * 功能   应用程序主函数,根据输入参数 
  15.  *      删除、复制、重命名文件 
  16.  * 
  17.  * 参数   删除文件: 
  18.  *          -d 文件路径 
  19.  *      将文件路径1的文件复制到文件路径2: 
  20.  *          -c 文件路径1 文件路径2 
  21.  *      将文件路径1的文件移动、重命名为文件路径2的文件 
  22.  *          -m 文件路径1 文件路径2 
  23.  **************************************/  
  24. int main(int argc, PCHAR argv[])  
  25. {  
  26.     LPSTR y="c:/2.bat";  
  27. LPSTR x="c:/1.bat";  
  28.     //-d参数,删除文件。   
  29.     if(0==lstrcmp("-d",argv[1]) && argc==3)  
  30.     {  
  31.         if(!DeleteFile(argv[2]))  
  32.         {  
  33.             printf("删除文件错误:%x/n",GetLastError());  
  34.         }  
  35.         else  
  36.         {  
  37.             printf("删除成功!/n");  
  38.         }  
  39.     }  
  40.     //-c参数,复制文件。   
  41.     //如果文件存在,询问用户是否覆盖   
  42.     else if(0==lstrcmp("-c",argv[1]) && argc==4)  
  43.     {  
  44.         //复制,不覆盖已经存在的文件   
  45.         if(!CopyFile(argv[2],argv[3],TRUE))  
  46.         {  
  47.             //LastError == 0x50,文件存在。   
  48.             if(GetLastError() == 0x50)  
  49.             {  
  50.                 printf("文件%s已经存在,是否覆盖?y/n:",argv[3]);  
  51.                 if('y'==getchar())  
  52.                 {  
  53.                     //复制,覆盖已经存在的文件。   
  54.                     if(!CopyFile(argv[2],argv[3],FALSE))  
  55.                     {  
  56.                         printf("复制文件错误,%d/n",GetLastError());  
  57.                     }  
  58.                     else  
  59.                     {  
  60.                         printf("复制成功!/n");  
  61.                     }  
  62.                 }  
  63.                 else  
  64.                 {  
  65.                     return 0;  
  66.                 }  
  67.             }  
  68.         }  
  69.         else  
  70.         {  
  71.             printf("复制成功!/n");  
  72.         }  
  73.     }  
  74.     //-m参数,移动、重命名文件。   
  75.     else if(0==lstrcmp("-m",argv[1]) && argc==4)  
  76.     {  
  77.         if(!MoveFile( x,y))  
  78.         {  
  79.             printf("移动文件错误:%d/n",GetLastError());  
  80.         }  
  81.         else  
  82.         {  
  83.             printf("移动文件成功!/n");  
  84.         }  
  85.     }  
  86.     else  
  87.     {  
  88.         printf("参数错误!/n");  
  89.     }  
  90. }  

 



 4.3.3 创建目录

编程实现创建目录是非常简单的,只要使用API函数CreateDirectory即可。
1. 关键API
(1) Createdirectory
函数原型如下:
◇参数
lpPathName:输入参数,所要创建的目录名或路径。
lpSecurityAttributes:输入参数,设置为NULL。
◇返回值
返回BOOL值,表示是否成功。
◇使用说明
如果程序返回失败,可以使用GetLastError函数获取错误信息。可能的值包括ERROR
ALREADY EXISTS(文件夹已经存在)和ERROR PATH NOT FOUND(路径不存在)。

[cpp] view plaincopyprint?

  1. /* ************************************ 
  2. *《精通Windows API》  
  3. * 示例代码 
  4. * dir.c 
  5. * 4.3.3 创建目录 
  6. **************************************/  
  7.   
  8. /* 头文件 */  
  9. #include <windows.h>   
  10. #include <stdio.h>   
  11.   
  12. /* ************************************ 
  13. * int main(void) 
  14. * 功能    演示使用CreateDirectory创建目录 
  15. **************************************/  
  16. int main(void)  
  17. {  
  18.     //在程序的当前目录下创建“sub_dir”子目录   
  19.     LPSTR szDirPath = "sub_dir";  
  20.     if (!CreateDirectory(szDirPath, NULL))   
  21.     {   
  22.         printf("创建目录 %s 错误。/n",szDirPath);   
  23.         return 1;  
  24.     }  
  25.   
  26.     //在C盘下创建目录“example_dir”   
  27.     szDirPath = "C://example_dir";  
  28.     if (!CreateDirectory(szDirPath, NULL))   
  29.     {   
  30.         printf("创建目录 %s 错误。/n",szDirPath);   
  31.         return 1;  
  32.     }   
  33.     printf("成功/n");   
  34.   
  35.     return 0;  
  36. }  

 

 


 


 4.3.4 获取程序所在的目录、程序模块路径,获取和设置当前目录


Windows系统提供一组API实现对程序运行时相关目录的获取和设置。用户可以使用
GetCurrentDirectory和SetCurrentDirectory获取程序的当前目录,获取模块的路径使用
GetModuleFileName,如果以NULL参数调用GetModuleFileName,将会返回当前模块的路径。如果在程序主模块(exe)中获取当前模块路径,便可以从当前模块的路径中提取出程序运行时所在的路径。
1.关键API
(1)GetCurrentDirectory。
获取进程的当前目录,函数原型如下:

 (2)SetCurrentDirectory。
设置进程的当前目录,函数原型如下:

(3)GetModuleFileName。
获取模块文件名,当第一个参数为NULL时获取当前模块路径,函数原型如下:

[cpp] view plaincopyprint?

  1. /* ************************************ 
  2. *《精通Windows API》  
  3. * 示例代码 
  4. * cur_mod_dir.c 
  5. * 4.3.4 获取当前目录、获取程序所在的目录、获取模块路径 
  6. **************************************/  
  7.   
  8. /* 头文件 */  
  9. #include <windows.h>   
  10. #include <stdio.h>   
  11.   
  12. /* ************************************ 
  13. * int main(void) 
  14. * 功能    演示使用设置获取当前路径 
  15. *       演示获取模块路径 
  16. **************************************/  
  17. int main(void)  
  18. {  
  19.     //用于存储当前路径   
  20.     CHAR szCurrentDirectory[MAX_PATH];  
  21.     //用于存储模块路径   
  22.     CHAR szMoudlePath[MAX_PATH];  
  23.     //Kernel32文件名与句柄   
  24.     LPSTR szKernel32 = "kernel32.dll";  
  25.     HMODULE hKernel32;  
  26.     //当前路径的长度,也用于判断获取是否成功   
  27.     DWORD dwCurDirPathLen;  
  28.       
  29.     //获取进程当前目录   
  30.     dwCurDirPathLen =   
  31.         GetCurrentDirectory(MAX_PATH,szCurrentDirectory);  
  32.     if(dwCurDirPathLen == 0)  
  33.     {  
  34.         printf("获取当前目录错误。/n");   
  35.         return 0;  
  36.     }  
  37.     printf("进程当前目录为 %s /n",szCurrentDirectory);   
  38.       
  39.     //将进程当前目录设置为“C:/”   
  40.     lstrcpy(szCurrentDirectory, "C://");  
  41.     if(!SetCurrentDirectory(szCurrentDirectory))  
  42.     {  
  43.         printf("设置当前目录错误。/n");   
  44.         return 0;  
  45.     }  
  46.     printf("已经设置当前目录为 %s /n",szCurrentDirectory);   
  47.   
  48.     //在当前目录下创建子目录“current_dir”   
  49.     //运行完成后C:盘下将出现文件夹“current_dir”   
  50.     CreateDirectory("current_dir", NULL);  
  51.   
  52.     //再次获取系统当前目录   
  53.     dwCurDirPathLen =   
  54.         GetCurrentDirectory(MAX_PATH,szCurrentDirectory);  
  55.     if(dwCurDirPathLen == 0)  
  56.     {  
  57.         printf("获取当前目录错误。/n");   
  58.         return 0;  
  59.     }  
  60.     printf("GetCurrentDirectory获取当前目录为 %s /n",  
  61.         szCurrentDirectory);   
  62.   
  63.     //使用NULL参数,获取本模块的路径。   
  64.     if(!GetModuleFileName(NULL,szMoudlePath,MAX_PATH))  
  65.     {  
  66.         printf("获取模块路径录错误。/n");   
  67.         return 0;  
  68.     }  
  69.     printf("本模块路径 %s /n",szMoudlePath);  
  70.   
  71.     //获取Kernel32.dll的模块句柄。   
  72.     hKernel32 = LoadLibrary(szKernel32);  
  73.   
  74.     //使用Kernel32.dll的模块句柄,获取其路径。   
  75.     if(!GetModuleFileName(hKernel32,szMoudlePath,MAX_PATH))  
  76.     {  
  77.         printf("获取模块路径错误。/n");   
  78.         return 0;  
  79.     }  
  80.     printf("kernel32模块路径 %s /n",szMoudlePath);   
  81.   
  82.     return 0;  
  83. }  

 

 

 



 

 

4.3.5 查找文件、遍历指定目录下的文件和子目录

Windows API中,有一组专门的函数和结构,用于遍历目录,它们是FindFirstFile函数、
FindNextFile函数和WIN32_FIND_DATA结构。使用FindFirstFile和FindNextFile函数并与do-while循环结合,可以完成遍历目录的任务,详见实例4-10。
值得一提的是,FindFirstFile输入参数的路径需使用通配符,也就是用户可以根据一些条件来对查找的文件作简单的过滤。实例4-10讲解查找特定目录下的所有文件和文件夹。读者可根据自己的需要,指定查找文件的条件。
1.关键API
(1)FindFirstFile。
查找第一个目录或文件,获取查找句柄,函数原型如下:

(2)FindNextFile
对文件、文件夹进行循环查找,函数原型如下:

2.关键结构
WIN32_FIND_DATA结构用于表示找到的文件,结构中包括文件、目录的名字,创建、最后访问和最后写入时间,文件大小、文件属性等。

[cpp] view plaincopyprint?

  1. /* ************************************ 
  2. *《精通Windows API》  
  3. * 示例代码 
  4. * sub_dir.c 
  5. * 4.3.5 遍历目录下的文件和子目录 
  6. **************************************/  
  7.   
  8. /* 头文件 */  
  9. #include <windows.h>   
  10. #include <stdio.h>   
  11.   
  12. /* ************************************ 
  13. * DWORD EnumerateFileInDrectory(LPSTR szPath) 
  14. * 功能    遍历目录下的文件和子目录,将显示文件的 
  15. *       文件和文件夹隐藏、加密的属性 
  16. * 参数    LPTSTR szPath,为需遍历的路径 
  17. * 返回值   0代表执行完成,1代码发生错误 
  18. **************************************/  
  19. DWORD EnumerateFileInDrectory(LPSTR szPath)  
  20. {  
  21.     WIN32_FIND_DATA FindFileData;  
  22.     HANDLE hListFile;  
  23.     CHAR szFilePath[MAX_PATH];  
  24.       
  25.     //构造代表子目录和文件夹路径的字符串,使用通配符“*”   
  26.     lstrcpy(szFilePath, szPath);      
  27.     //注释的代码可以用于查找所有以“.txt结尾”的文件。   
  28.     //lstrcat(szFilePath, "//*.txt");   
  29.     lstrcat(szFilePath, "//*");  
  30.     //查找第一个文件/目录,获得查找句柄   
  31.     hListFile = FindFirstFile(szFilePath,&FindFileData);  
  32.     //判断句柄   
  33.     if(hListFile==INVALID_HANDLE_VALUE)  
  34.     {  
  35.         printf("错误:%d",GetLastError());  
  36.         return 1;  
  37.     }  
  38.     else  
  39.     {         
  40.         do  
  41.         {  
  42.             /*  如果不想显示代表本级目录和上级目录的“.”和“..”,  
  43.                 可以使用注释部分的代码过滤。  
  44.             if(lstrcmp(FindFileData.cFileName,TEXT("."))==0||  
  45.                 lstrcmp(FindFileData.cFileName,TEXT(".."))==0)  
  46.             {  
  47.                 continue;  
  48.             }  
  49.             */  
  50.             //打印文件名、目录名   
  51.             printf("%s/t/t",FindFileData.cFileName);  
  52.             //判断文件属性,加密文件或文件夹   
  53.             if(FindFileData.dwFileAttributes&FILE_ATTRIBUTE_ENCRYPTED)  
  54.             {  
  55.                 printf("<加密> ");  
  56.             }  
  57.             //判断文件属性,隐藏文件或文件夹   
  58.             if(FindFileData.dwFileAttributes&FILE_ATTRIBUTE_HIDDEN)  
  59.             {  
  60.                 printf("<隐藏> ");  
  61.             }  
  62.             //判断文件属性,目录   
  63.             if(FindFileData.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)  
  64.             {  
  65.                 printf("<DIR> ");  
  66.             }  
  67.             //读者可根据文件属性表中的内容自行添加判断文件属性。   
  68.             printf("/n");  
  69.         }  
  70.         while(FindNextFile(hListFile, &FindFileData));  
  71.     }  
  72.     return 0;  
  73. }  
  74.   
  75. /* ************************************ 
  76. * int main(int argc, PCHAR argv[]) 
  77. * 功能    调用ListFileInDrectory 
  78. *       遍历目录下的文件和子目录 
  79. * 参数    argv[1]为需遍历的路径,如果为空则获取 
  80. *       当前路径 
  81. **************************************/  
  82. int main(int argc, PCHAR argv[])  
  83. {     
  84.     if(argc == 2)  
  85.     {  
  86.         EnumerateFileInDrectory(argv[1]);  
  87.     }  
  88.     else   
  89.     {  
  90.         CHAR szCurrentPath[MAX_PATH];  
  91.         GetCurrentDirectory(MAX_PATH,szCurrentPath);  
  92.         EnumerateFileInDrectory(szCurrentPath);  
  93.     }  
  94.     return 0;  
  95. }  

 

 



 4.3.6 递归遍历目录树

 

在实例4-10的基础上稍加改造,进行循环递归调用,采用树形结构深度遍历的方法。可以遍历指定目录中的所有文件、包括子目录中的文件。代码实现如实例4-11所示。

[cpp] view plaincopyprint?

  1. /* ************************************ 
  2. *《精通Windows API》  
  3. * 示例代码 
  4. * tree.c 
  5. * 4.3.6 递归遍历目录树 
  6. * 2007年10月 
  7. **************************************/  
  8.   
  9. /* 头文件 */  
  10. #include <windows.h>   
  11. #include <stdio.h>   
  12.   
  13. /* 预处理申明 */  
  14. #pragma comment (lib, "User32.lib")   
  15.   
  16. /* 函数申明 */  
  17. DWORD ListAllFileInDrectory(LPSTR szPath);  
  18.   
  19. /* 全局变量 */  
  20. //记录所有的文件和目录数   
  21. DWORD dwTotalFileNum = 0;  
  22.   
  23.   
  24. /* ************************************ 
  25. * DWORD ListAllFileInDrectory(LPSTR szPath) 
  26. * 功能    遍历目录及所有子目录,打印路径 
  27. * 参数    LPTSTR szPath,为需遍历的目录 
  28. * 返回值   0代表执行完成,1代码发生错误 
  29. **************************************/  
  30. DWORD ListAllFileInDrectory(LPSTR szPath)  
  31. {  
  32.     CHAR szFilePath[MAX_PATH];  
  33.   
  34.     WIN32_FIND_DATA FindFileData;  
  35.     HANDLE hListFile;  
  36.     CHAR szFullPath[MAX_PATH];  
  37.   
  38.     //构造代表子目录和文件夹路径的字符串,使用通配符“*”   
  39.     lstrcpy(szFilePath, szPath);  
  40.     lstrcat(szFilePath, "//*");  
  41.     //查找第一个文件/目录,获得查找句柄   
  42.     hListFile = FindFirstFile(szFilePath,&FindFileData);  
  43.   
  44.     if(hListFile==INVALID_HANDLE_VALUE)  
  45.     {  
  46.         printf("错误:%d",GetLastError());  
  47.         return 1;  
  48.     }  
  49.     else  
  50.     {         
  51.         do  
  52.         {  
  53.             //  过滤“.”和“..”,不需要遍历   
  54.             if(lstrcmp(FindFileData.cFileName,TEXT("."))==0||  
  55.                 lstrcmp(FindFileData.cFileName,TEXT(".."))==0)  
  56.             {  
  57.                 continue;  
  58.             }  
  59.             //构造成全路径   
  60.             wsprintf(szFullPath,"%s//%s",  
  61.                 szPath,FindFileData.cFileName);  
  62.             dwTotalFileNum++;  
  63.             //打印   
  64.             printf("/n%d/t%s/t",dwTotalFileNum,szFullPath);  
  65.   
  66.             //如果是目录,则递归调用,列举下级目录   
  67.             if(FindFileData.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)  
  68.             {  
  69.                 printf("<DIR>");  
  70.                 ListAllFileInDrectory(szFullPath);  
  71.             }             
  72.         }  
  73.         while(FindNextFile(hListFile, &FindFileData));  
  74.     }  
  75.     return 0;  
  76. }  
  77.   
  78.   
  79. /* ************************************  
  80. * int main(int argc, PCHAR argv[])  
  81. * 功能    调用ListAllFileInDrectory  
  82. *       遍历目录下的文件和子目录  
  83. *  
  84. * 参数    argv[1]为需遍历的路径,如果为空则获取  
  85. *       当前路径  
  86. *  
  87. * 2007年10月  
  88. *  
  89. **************************************/  
  90. int main(int argc, PCHAR argv[])  
  91. {     
  92.     if(argc == 2)  
  93.     {  
  94.         ListAllFileInDrectory(argv[1]);  
  95.     }  
  96.     else   
  97.     {  
  98.         CHAR szCurrentPath[MAX_PATH];  
  99.         GetCurrentDirectory(MAX_PATH,szCurrentPath);  
  100.         ListAllFileInDrectory(szCurrentPath);  
  101.     }  
  102.     return 0;  
  103. }  

 

 

 



 

4.3.7 获取、设置文件属性和时间


为了获取文件属性,用户可以使用GetFileAttributes与GetFileAttributesEx函数。
GetFileAttributesEx函数除了返回文件属性外,还返回文件时间信息、文件大小等。
GetFileAttributesEx将返回结果保存在WIN32_FILE_ATTRIBUTE DATA结构中。
获取的文件时间是以FILETIME格式存在的,如果要正确显示,还需要对其时区进行调整,调整为本地时区,然后转换为系统时间格式,便于显示。
前面在获取文件大小时已经介绍,NTFS文件系统使用了64位数据来表示文件大小。因为32位的数据最多只能表示4GB的大小。Windows将其分为了高32位和低32位,两个都需要使用到,这一点尤其要在对大于4GB的文件操作时注意。
1.关键API
(1)GetFileAttributeS。
获取文件或目录的属牲-函数原型如下:

(2)GetFileAttributesEx。
获取文件或目录的属性、时间、大小,以WIN32_FILE ATTRIBUTE_DATA结构的形式返回
结果,函数原型如下:

(3) SetFileAttributes.
设置文件或目录的属性,函数原型如下:

(4)FileTimeToLocalFileTime。
把文件时间转换为本地的文件时间,函数原型如下:

5)FileTimeToSystemTime
将文件时间转换为系统时间(SYSTEMTIME格式),便于显示,函数原型如下:

2.关键数据结构
(1) FILETIM。
此结构用最小的数据量表示的时间,但是不便于用户查看和显示。通过API获取的系统时间都是这种格式的。如果要使用显示,可以使用FileTimeToSystemTime转换为便于显示的SYSTEMTIME结构。

(2) SYSTEMTIME。
此结构使用了较为直观的方式表示时间。

(3) WIN32_FILE ATTRIBUTE_DATA。
GetFileAttributesEx使用这个结构表示返回结果,包括文件属性、文件创建时间、文件最后访问时间、文件最后写入时间和文件大小。

[cpp] view plaincopyprint?

  1. /* ************************************ 
  2.  *《精通Windows API》  
  3.  * 示例代码 
  4.  * attr.c 
  5.  * 4.3.7  获取、设置文件属性和时间 
  6.  **************************************/  
  7.   
  8. /* 头文件 */  
  • #include <windows.h>   
  • #include <stdio.h>   
  •   
  • /* 函数申明 */  
  • DWORD ShowFileTime(PFILETIME lptime);  
  • DWORD ShowFileSize(DWORD dwFileSizeHigh,DWORD dwFileSizeLow);  
  • DWORD ShowFileAttrInfo(DWORD dwAttribute);  
  • DWORD SetFileHiddenAndReadonly(LPSTR szFileName);  
  •   
  • /* ************************************ 
  •  * DWORD ShowFileAttributes(LPSTR szPath) 
  •  * 功能   获取并显示文件属性, 
  •  *      调用ShowFileTime、ShowFileSize和 
  •  *      ShowFileAttrInfo函数 
  •  * 
  •  * 参数   LPTSTR szPath,获取并显示此文件的属性 
  •  * 
  •  * 返回值  0代表执行完成,1代码发生错误 
  •  **************************************/  
  • DWORD ShowFileAttributes(LPSTR szPath)  
  • {  
  •     //文件属性结构   
  •     WIN32_FILE_ATTRIBUTE_DATA wfad;  
  •     printf("文件:%s/n",szPath);  
  •     //获取文件属性   
  •     if(!GetFileAttributesEx(szPath,  
  •         GetFileExInfoStandard,  
  •         &wfad))  
  •     {  
  •         printf("获取文件属性错误:%d/n",GetLastError());  
  •         return 1;  
  •     }  
  •     //显示相关时间   
  •     printf("创建时间:/t");  
  •     ShowFileTime(&(wfad.ftCreationTime));  
  •     printf("最后访问时间:/t");  
  •     ShowFileTime(&(wfad.ftLastAccessTime));  
  •     printf("最后修改时间:/t");  
  •     ShowFileTime(&(wfad.ftLastWriteTime));  
  •     //显示文件大小   
  •     ShowFileSize(wfad.nFileSizeHigh,wfad.nFileSizeLow);  
  •     //显示文件属性   
  •     ShowFileAttrInfo(wfad.dwFileAttributes);  
  •   
  •     return 0;  
  • }  
  •   
  • /* ************************************ 
  •  * DWORD ShowFileAttrInfo(DWORD dwAttribute) 
  •  * 功能   打印将文件属性 
  •  * 
  •  * 参数   DWORD dwAttribute,文件属性 
  •  * 
  •  * 返回值 0 
  •  **************************************/  
  • DWORD ShowFileAttrInfo(DWORD dwAttribute)  
  • {  
  •     //依次判断属性,并显示。   
  •     printf("文件属性:/t");  
  •     if(dwAttribute&FILE_ATTRIBUTE_ARCHIVE)  
  •         printf("<ARCHIVE> ");  
  •     if(dwAttribute&FILE_ATTRIBUTE_COMPRESSED)  
  •         printf("<压缩> ");  
  •     if(dwAttribute&FILE_ATTRIBUTE_DIRECTORY)  
  •         printf("<目录> ");  
  •     if(dwAttribute&FILE_ATTRIBUTE_ENCRYPTED)  
  •         printf("<加密> ");  
  •     if(dwAttribute&FILE_ATTRIBUTE_HIDDEN)  
  •         printf("<隐藏> ");  
  •     if(dwAttribute&FILE_ATTRIBUTE_NORMAL)  
  •         printf("<NORMAL> ");  
  •     if(dwAttribute&FILE_ATTRIBUTE_OFFLINE)  
  •         printf("<OFFLINE> ");  
  •     if(dwAttribute&FILE_ATTRIBUTE_READONLY)  
  •         printf("<只读> ");  
  •     if(dwAttribute&FILE_ATTRIBUTE_SPARSE_FILE)  
  •         printf("<SPARSE> ");  
  •     if(dwAttribute&FILE_ATTRIBUTE_SYSTEM)  
  •         printf("<系统文件> ");  
  •     if(dwAttribute&FILE_ATTRIBUTE_TEMPORARY)  
  •         printf("<临时文件> ");  
  •   
  •     printf("/n");  
  •   
  •     return 0;  
  • }  
  • /* ************************************ 
  •  * DWORD ShowFileSize(DWORD dwFileSizeHigh, DWORD dwFileSizeLow) 
  •  * 功能   打印文件大小信息 
  •  * 
  •  * 参数   DWORD dwFileSizeHigh,文件大小高32位 
  •  *      DWORD dwFileSizeLow,文件大小低32位 
  •  * 
  •  * 返回值 0 
  •  **************************************/  
  • DWORD ShowFileSize(DWORD dwFileSizeHigh, DWORD dwFileSizeLow)  
  • {  
  •     ULONGLONG liFileSize;  
  •     liFileSize = dwFileSizeHigh;  
  •   
  •     //高们移动32位   
  •     liFileSize <<= sizeof(DWORD)*8;  
  •     liFileSize += dwFileSizeLow;  
  •     printf("文件大小:/t%I64u 字节/n",liFileSize);  
  •     return 0;  
  • }  
  •   
  • /* ************************************ 
  •  *DWORD ShowFileTime(PFILETIME lptime) 
  •  * 功能   轮换文件时间,将打印 
  •  * 
  •  * 参数   PFILETIME lptime,指向文件时间的指针 
  •  * 
  •  * 返回值 0 
  •  **************************************/  
  • DWORD ShowFileTime(PFILETIME lptime)  
  • {  
  •     //文件时间结构   
  •     FILETIME ftLocal;  
  •     //系统时间结构   
  •     SYSTEMTIME st;  
  •     //调整为系统所在时区的时间   
  •     FileTimeToLocalFileTime(  
  •         lptime,  
  •         &ftLocal  
  •         );  
  •     //将文件时间转换为SYSTEMTIME格式,便于显示。   
  •     FileTimeToSystemTime(  
  •         &ftLocal,  
  •         &st  
  •         );  
  •     //显示时间信息字符串   
  •     printf("%4d年%.2d月%#02d日,%.2d:%.2d:%.2d/n",  
  •         st.wYear,st.wMonth,st.wDay,st.wHour,st.wMinute,st.wSecond);  
  •   
  •     return 0;  
  • }  
  •   
  • /* ************************************ 
  •  * DWORD SetFileHiddenAndReadonly(LPSTR szFileName) 
  •  * 功能   将指定的文件设置为隐藏和只读 
  •  * 
  •  * 参数   LPSTR szFileName,文件路径 
  •  * 
  •  * 返回值 0 
  •  **************************************/  
  • DWORD SetFileHiddenAndReadonly(LPSTR szFileName)  
  • {  
  •     //获取原来的文件属性   
  •     DWORD dwFileAttributes = GetFileAttributes(szFileName);  
  •     //将只读和隐藏属性附加到原来的文件属性上   
  •     dwFileAttributes |= FILE_ATTRIBUTE_READONLY;  
  •     dwFileAttributes |= FILE_ATTRIBUTE_HIDDEN;  
  •     //设置文件属性,并判断是否成功。   
  •     if(SetFileAttributes(szFileName, dwFileAttributes))  
  •     {  
  •         printf("文件%s的隐藏和属性设置成功/n",szFileName);  
  •     }  
  •     else  
  •     {  
  •         printf("属性设置; %d/n",GetLastError());  
  •     }  
  •     return 0;  
  • }  
  •   
  • /* ************************************ 
  •  * int main(int argc, PCHAR argv[]) 
  •  * 功能   设置和获取文件属性等 
  •  * 
  •  * 参数   显示第一个参数指定文件的属性、时间、大小 
  •  *      将第二个参数的属性设置为隐藏、只读。 
  •  * 
  •  * 返回值  0代表执行完成,1代码发生错误 
  •  **************************************/  
  • int main(int argc, PCHAR argv[])  
  • {     
  •     if(argc != 3)  
  •     {  
  •         printf("请输入参数/n");  
  •         printf("显示第一个参数指定文件的属性、时间、大小;/n");  
  •         printf("将第二个参数的属性设置为隐藏、只读。");  
  •         return 1;  
  •     }  
  •     ShowFileAttributes(argv[1]);  
  •     SetFileHiddenAndReadonly(argv[2]);  
  •     return 0;  
  • }  

 

 

 


 

 

 

 


 

 

 

 4.4 内存映射文件


本节介绍Mapping File、文件句柄等较高级操作。本节将通过以下几个实例来讲解高级文件系统操作的API。
◇ 使用Mapping File提高文件读写的效率。
◇通过Mapping File在进程间共享内存。
◇通过文件句柄获得文件路径。
4.4.1 使用Mapping File提高文件读写的效率
文件映射( mapping)是一种在将文件内容映射到进程的虚拟地址空间的技术。视图(View)是一段虚拟地址空间,进程可以通过View来存取文件的内容,视图是一段内存,可以使用指针来操作视图。使用的文件映射之后,读写文件就如同对读写内存一样简单。在使用文件映射时需要创建映射对象,映射对象分为命名的和未命名的。映射对象还存取权限。
使用文件映射至少有3个好处,一是因为文件是存储于硬盘上的,而文件视图是一段内存,使用文件映射操作时更方便;二是效率更高;三是可以在不同的进程间共享数据。
文件映射依赖于系统虚拟内存管理的分页机制。
本节将演示如何使用文件映射,下一节将演示如何使用文件映射来进行内存共享。
1. 关键API
(1)GetSystemInfo
获取系统信息,在实例 4-14中用于获取系统内存分配粒度。有关内存分配粒度的概念参见第5章和虚拟内存管理相关章节。
(2)CreateFileMapping。
创建mapping对象,函数原型如下

(3)MapViewOfFile。
创建视图,将文件mapping映射到当前进程内存虚拟地址空间。函数原型如下:

 (4)FlushViewOfFile。
将视图中的文件数据写入到磁盘上。调用此参数后,对映射视图的内存操作将会及时反映到硬件中的文件。函数原型如下:

◇使用说明
如果不调用此函数,数据最终也会写回到硬盘,调用此函数后,数据会立刻写回到硬盘。
(5) FillMemory、CopyMemory。内存操作函数,分别为填充内存和复制内存,详见第5章

 

[cpp] view plaincopyprint?

  1. /* ************************************ 
  2. *《精通Windows API》  
  3. * 示例代码 
  4. * file_map.c 
  5. * 4.4.1  使用Mapping File提高文件读写的效率 
  6. **************************************/  
  7.   
  8. /* 头文件 */  
  9. #include <windows.h>   
  10. #include <stdio.h>   
  11. /* 预处理申明 */  
  12. #define BUFFSIZE 1024                   // 内存大小   
  13. #define FILE_MAP_START 0x28804          // 文件映射的起始的位置   
  14. /* 全局变量 */  
  15. LPTSTR lpcTheFile = TEXT("test.dat");   // 文件名   
  16.   
  17. /* ************************************ 
  18. * int main(void) 
  19. * 功能    演示使用文件mapping 
  20. * 参数    无 
  21. * 返回值   0代表执行完成,1代表发生错误 
  22. **************************************/  
  23. int main(void)  
  24. {  
  25.     HANDLE hMapFile;      // 文件内存映射区域的句柄   
  26.     HANDLE hFile;         // 文件的句柄   
  27.     DWORD dBytesWritten;  // 写入的字节数   
  28.     DWORD dwFileSize;     // 文件大小   
  29.     DWORD dwFileMapSize;  // 文件映射的大小   
  30.     DWORD dwMapViewSize;  // 视图(View)的大小   
  31.     DWORD dwFileMapStart; // 文件映射视图的起始位置   
  32.     DWORD dwSysGran;      // 系统内存分配的粒度   
  33.     SYSTEM_INFO SysInfo;  // 系统信息   
  34.     LPVOID lpMapAddress;  // 内在映射区域的起始位置   
  35.     PCHAR pData;            // 数据   
  36.     INT i;                // 循环变量   
  37.     INT iData;  
  38.     INT iViewDelta;  
  39.     BYTE cMapBuffer[32];  // 存储从mapping中计出的数据   
  40.   
  41.     // 创建一个文件   
  42.     hFile = CreateFile(lpcTheFile,   
  43.         GENERIC_READ | GENERIC_WRITE,  
  44.         0,   
  45.         NULL,  
  46.         CREATE_ALWAYS,   
  47.         FILE_ATTRIBUTE_NORMAL,   
  48.         NULL);  
  49.     //判断文件是否创建成功   
  50.     if (hFile == INVALID_HANDLE_VALUE)  
  51.     {  
  52.         printf("CreateFile error/n",GetLastError);  
  53.         return 1;  
  54.     }  
  55.     // 依次写入整数,一共写入65535个整数   
  56.     // 在32位平台下,大小为65535*32   
  57.     for (i=0; i<65535; i++)   
  58.     {  
  59.         WriteFile (hFile, &i, sizeof (i), &dBytesWritten, NULL);  
  60.     }  
  61.     // 查看写入完成后的文件大小   
  62.     dwFileSize = GetFileSize(hFile,  NULL);  
  63.     printf("文件大小: %d/n", dwFileSize);  
  64.   
  65.     //获取系统信息,内存分配粒度   
  66.     //获取分配粒度,进行下面的几个计算,   
  67.     //目的是为了映射的数据与系统内存分配粒度对齐,提高内存访问效率   
  68.     GetSystemInfo(&SysInfo);  
  69.     dwSysGran = SysInfo.dwAllocationGranularity;  
  70.   
  71.     //计算mapping的起始位置   
  72.     dwFileMapStart = (FILE_MAP_START / dwSysGran) * dwSysGran;  
  73.     // 计算mapping view的大小   
  74.     dwMapViewSize = (FILE_MAP_START % dwSysGran) + BUFFSIZE;  
  75.     // 计算mapping的大小   
  76.     dwFileMapSize = FILE_MAP_START + BUFFSIZE;  
  77.     // 计算需要读取的数据的偏移   
  78.     iViewDelta = FILE_MAP_START - dwFileMapStart;  
  79.   
  80.     // 创建File mapping   
  81.     hMapFile = CreateFileMapping( hFile,          // 需要映射的文件的句柄   
  82.         NULL,           // 安全选项:默认   
  83.         PAGE_READWRITE, // 可读,可写   
  84.         0,              // mapping对象的大小,高位   
  85.         dwFileMapSize,  // mapping对象的大小,低位   
  86.         NULL);          // mapping对象的名字   
  87.     if (hMapFile == NULL)   
  88.     {  
  89.         printf("CreateFileMapping error: %d/n", GetLastError() );  
  90.         return 1;  
  91.     }  
  92.   
  93.     // 映射view   
  94.     lpMapAddress = MapViewOfFile(hMapFile,            // mapping对象的句柄   
  95.         FILE_MAP_ALL_ACCESS, // 可读,可写   
  96.         0,                   // 映射的文件偏移,高32位   
  97.         dwFileMapStart,      // 映射的文件偏移,低32位   
  98.         dwMapViewSize);      // 映射到View的数据大小   
  99.     if (lpMapAddress == NULL)   
  100.     {  
  101.         printf("MapViewOfFile error: %d/n", GetLastError());  
  102.         return 1;  
  103.     }  
  104.   
  105.     printf ("文件map view相对于文件的起始位置: 0x%x/n",  
  106.         dwFileMapStart);  
  107.     printf ("文件map view的大小:0x%x/n",     dwMapViewSize);  
  108.     printf ("文件mapping对象的大小:0x%x/n", dwFileMapSize);  
  109.     printf ("从相对于map view 0x%x 字节的位置读取数据,", iViewDelta);  
  110.   
  111.     // 将指向数据的指针偏移,到达我们关心的地方   
  112.     pData = (PCHAR) lpMapAddress + iViewDelta;  
  113.     // 读取数据,赋值给变量   
  114.     iData = *(PINT)pData;  
  115.     // 显示读取的数据   
  116.     printf ("为:0x%.8x/n", iData);  
  117.   
  118.     // 从mapping中复制数据,32个字节,并打印   
  119.     CopyMemory(cMapBuffer,lpMapAddress,32);  
  120.     printf("lpMapAddress起始的32字节是:");  
  121.     for(i=0; i<32; i++)  
  122.     {  
  123.         printf("0x%.2x ",cMapBuffer[i]);  
  124.     }  
  125.     // 将mapping的前32个字节用0xff填充   
  126.     FillMemory(lpMapAddress,32,(BYTE)0xff);  
  127.     // 将映射的数据写回到硬盘上   
  128.     FlushViewOfFile(lpMapAddress,dwMapViewSize);  
  129.     printf("/n已经将lpMapAddress开始的32字节使用0xff填充。/n");  
  130.   
  131.     // 关闭mapping对象   
  132.     if(!CloseHandle(hMapFile))   
  133.     {  
  134.         printf("/nclosing the mapping object error %d!",  
  135.             GetLastError());  
  136.     }  
  137.     //关闭文件   
  138.     if(!CloseHandle(hFile))   
  139.     {  
  140.         printf("/nError %ld occurred closing the file!",  
  141.             GetLastError());  
  142.     }  
  143.   
  144.     return 0;  
  145. }  

 

 




4.4.2 通过Mapping File在进程间传递和共享数据
进程间通信、共享数据有很多种方法,文件映射是常用的一种方法。因为mapping对象
系统中是全局的,一个进程创建的Mapping对象可以从另外一个进程中打开,映射视图就
进程间共享的内存了。一般在共享的内存数据量比较大时,选择使用文件映射进行共享。
1.关键API
(1)OpenFileMapping。
打开已经存在的文件映射,函数原型如下:

(2) UnmapViewO伍ile。
取消文件映射,函数原型如下:

[cpp] view plaincopyprint?

  1. /* ************************************ 
  2. *《精通Windows API》 
  3. * 示例代码 
  4. * pro_s1.c 
  5. * 4.4.2  通过Mapping File在进程间共享内存 
  6. **************************************/  
  7. /* 头文件 */  
  8. #include <windows.h>   
  9. #include <stdio.h>   
  10. #include <conio.h>   
  11. /* 预处理申明 */  
  12. #define BUF_SIZE 256   
  13. /* 全局变量 */  
  14. LPTSTR szName = TEXT("SharedFileMappingObject");  
  15. LPTSTR szMsg = TEXT("进程的消息");  
  16.   
  17. /* ************************************ 
  18. * int main(void) 
  19. * 功能    演示文件mapping共享内存,写入数据到共享内存 
  20. * 参数    无 
  21. * 返回值   0代表执行完成,代表发生错误 
  22. **************************************/  
  23. void main(int argc, PCHAR argv[])  
  24. {  
  25.     //文件映射句柄   
  26.     HANDLE hMapFile;  
  27.     //共享数据缓冲区指针   
  28.     LPTSTR pBuf;  
  29.     //创建命名的文件映射,不代表任务硬盘上的文件   
  30.     hMapFile = CreateFileMapping(  
  31.         INVALID_HANDLE_VALUE,  
  32.         NULL,   
  33.         PAGE_READWRITE,  
  34.         0,  
  35.         BUF_SIZE,   
  36.         szName);  
  37.     if (hMapFile == NULL || hMapFile == INVALID_HANDLE_VALUE)   
  38.     {   
  39.         printf("CreateFileMapping error: %d/n", GetLastError());  
  40.         return;  
  41.     }  
  42.     //创建View   
  43.     pBuf = (LPTSTR) MapViewOfFile(hMapFile,  
  44.         FILE_MAP_ALL_ACCESS,  
  45.         0,                     
  46.         0,                     
  47.         BUF_SIZE);  
  48.     if (pBuf == NULL)   
  49.     {   
  50.         printf("MapViewOfFile error %d/n",  GetLastError());   
  51.         return;  
  52.     }  
  53.     //将共享数据复制到文件映射中,如果运行时输入了参数则使用参数   
  54.     if(argc==1)  
  55.     {  
  56.         CopyMemory((PVOID)pBuf, szMsg, strlen(szMsg));  
  57.     }  
  58.     else  
  59.     {  
  60.         DWORD dwCopyLen = (lstrlen(argv[1])<BUF_SIZE) ? lstrlen(argv[1]): BUF_SIZE;  
  61.         CopyMemory((PVOID)pBuf, argv[1], dwCopyLen);  
  62.     }  
  63.     printf("运行程序,完成运行后,按任意键退出。");  
  64.     _getch();  
  65.     //取消映射,退出   
  66.     UnmapViewOfFile(pBuf);  
  67.     CloseHandle(hMapFile);  
  68. }  

 

 



.实例4-15读取并显示共享数据
本实例代码从实例4-14共享的Mapping对象中读取数据,并将数据显示出来。实例4-14与实例4-15是两个进程,实现了进程间数据的共享。这两个进程可以通过各自的指针,对同一段内存进行读写。
本实例先打开指定对象名的Mapping对象(与实例4-14中使用的CreateFileMapping创建的Mapping对象需有一样的对象名),然后创建视图,从视图中读取数据。

[cpp] view plaincopyprint?

  1. /* ************************************ 
  2. *《精通Windows API》 
  3. * 示例代码 
  4. * pro_s2.c 
  5. * 4.4.2  通过Mapping File在进程间共享内存 
  6. **************************************/  
  7. #include <windows.h>   
  8. #include <stdio.h>   
  9. #include <conio.h>   
  10. /* 预处理申明*/  
  11. #pragma comment (lib, "User32.lib")   
  12. #define BUF_SIZE 256   
  13. /* 全局变量 */  
  14. TCHAR szName[]=TEXT("SharedFileMappingObject");  
  15.   
  16. /* ************************************ 
  17. * int main(void) 
  18. * 功能    演示文件mapping共享内存,从共享数据中读信息 
  19. * 参数    无 
  20. * 返回值   0代表执行完成,代表发生错误 
  21. **************************************/  
  22. void main()  
  23. {  
  24.     HANDLE hMapFile;  
  25.     LPTSTR pBuf;  
  26.     //打开文件mapping   
  27.     hMapFile = OpenFileMapping(  
  28.         FILE_MAP_ALL_ACCESS,  
  29.         FALSE,  
  30.         szName);   
  31.     if (hMapFile == NULL)   
  32.     {   
  33.         printf("OpenFileMapping error: %d./n",  GetLastError());  
  34.         return;  
  35.     }   
  36.     //映射   
  37.     pBuf = MapViewOfFile(hMapFile,  
  38.         FILE_MAP_ALL_ACCESS,  
  39.         0,                      
  40.         0,                      
  41.         BUF_SIZE);    
  42.     if (pBuf == NULL)   
  43.     {   
  44.         printf("MapViewOfFile error %d/n", GetLastError());   
  45.         return;  
  46.     }  
  47.     //消息得到的共享数据   
  48.     MessageBox(NULL, pBuf, TEXT("Process2"), MB_OK);  
  49.     //取消mapping,关闭句柄,返回   
  50.     UnmapViewOfFile(pBuf);  
  51.     CloseHandle(hMapFile);  
  52. }  

 

 

 


 

 


 

4.4.3 通过文件句柄获得文件路径
Windows系统提供了一个名为GetMappedFileName的API函数,这个函数可以实现从
mapping对象的句柄得到被映射文件的路径。但是路径是以设备名的形式给出的,如类似于
“/Device/HarddiskVolume3/1.TXT”的形式。
将设备名转换为路径名需要使用到一个API函数-QueryDosDevice,这个函数可以将驱动器的根路径转换为设备名,然后进行循环比较,可得文件路径。
1.关键API
(1)GetMappedFileName。
从映射对象获取被映射文件的文件设备名,函数原型如下:

(2)QueryDosDevice
获取MS_DOS设备名,函数原型如下:

◇返回值返回DWORD值,如果成功,则返回值为lpTargetPath指向字符串的长度,如果失败为0。
2.实例4-16通过文件句柄获取文件路径
GetFileNameFromHandle通过参数输入的句柄创建mapping对象,然后调用GetMapped
FileName函数,获得对象所映射的文件的设备名,然后使用QueryDosDevice函数循环判断
驱动器设备名与路径的关系,在找到正确的驱动器路径后,构造好文件路径并输出。

[cpp] view plaincopyprint?

  1. /* ************************************ 
  2. *《精通Windows API》 
  3. * 示例代码 
  4. * handle_path.cpp 
  5. * 4.4.3 通过文件句柄获取文件路径 
  6. **************************************/  
  7. /* 头文件*/  
  8. #include <windows.h>   
  9. #include <stdio.h>   
  10. #include <tchar.h>   
  11. #include <string.h>   
  12. #include <psapi.h>   
  13. /* 预处理申明*/  
  14. #pragma comment (lib, "Psapi.lib")   
  15. #define BUFSIZE 512   
  16. /* 函数申明*/  
  17. BOOL GetFileNameFromHandle(HANDLE hFile) ;  
  18.   
  19. /* ************************************ 
  20. * BOOL GetFileNameFromHandle(HANDLE hFile)  
  21. * 功能    从文件句柄获取文件路径 
  22. * 参数    ANDLE hFile,需要获得路径的文件句柄 
  23. * 返回值BOOL 是否成功。 
  24. **************************************/  
  25. BOOL GetFileNameFromHandle(HANDLE hFile)   
  26. {  
  27.     TCHAR pszFilename[MAX_PATH+1];  
  28.     HANDLE hFileMap;  
  29.     PVOID pMem;  
  30.   
  31.     // 获得文件大小,并决断是否为   
  32.     DWORD dwFileSizeHigh = 0;  
  33.     DWORD dwFileSizeLow = GetFileSize(hFile, &dwFileSizeHigh);   
  34.     if( dwFileSizeLow == 0 && dwFileSizeHigh == 0 )  
  35.     {  
  36.         printf("不能map文件大小为的文件./n");  
  37.         return FALSE;  
  38.     }  
  39.     // 创建mapping对象   
  40.     hFileMap = CreateFileMapping(hFile,   
  41.         NULL,   
  42.         PAGE_READONLY,  
  43.         0,   
  44.         1,  
  45.         NULL);  
  46.     if (!hFileMap)   
  47.     {  
  48.         printf("CreateFileMapping error: %d",GetLastError());  
  49.         return FALSE;  
  50.     }  
  51.   
  52.     pMem = MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, 1);  
  53.     if (!pMem)   
  54.     {  
  55.         printf("MapViewOfFile error: %d",GetLastError());  
  56.         return FALSE;  
  57.     }  
  58.     // 从mapping对象获得文件名   
  59.     if (0 == GetMappedFileName (GetCurrentProcess(),   
  60.         pMem,   
  61.         pszFilename,  
  62.         MAX_PATH))  
  63.     {  
  64.         printf("GetMappedFileName error: %d",GetLastError());  
  65.         return FALSE;  
  66.     }  
  67.     // 将设备名转换为路径   
  68.     TCHAR szTemp[BUFSIZE] = {0};  
  69.     if (0 == GetLogicalDriveStrings(BUFSIZE-1, szTemp))   
  70.     {  
  71.         printf("GetLogicalDriveStrings error: %d",GetLastError());  
  72.         return FALSE;  
  73.     }  
  74.     TCHAR szName[MAX_PATH];  
  75.     TCHAR szDrive[3] = {0};  
  76.     BOOL bFound = FALSE;  
  77.     PTCHAR p = szTemp;  
  78.     do   
  79.     {  
  80.         CopyMemory(szDrive,p,2*sizeof(TCHAR));  
  81.         // 通过路径查找设备名   
  82.         if (!QueryDosDevice(szDrive, szName, BUFSIZE))  
  83.         {  
  84.             printf("QueryDosDevice error: %d",GetLastError());  
  85.             return FALSE;  
  86.         }  
  87.         UINT uNameLen = lstrlen(szName);  
  88.         if (uNameLen < MAX_PATH)   
  89.         {  
  90.             //比较驱动器的设备名与文件设备名是否匹配   
  91.             bFound = strncmp(pszFilename, szName,uNameLen) == 0;  
  92.             if (bFound)   
  93.             {  
  94.                 //如果匹配,说明已经找到,构造路径。   
  95.                 TCHAR szTempFile[MAX_PATH];  
  96.                 wsprintf(szTempFile,  
  97.                     TEXT("%s%s"),  
  98.                     szDrive,  
  99.                     pszFilename+uNameLen);  
  100.                 lstrcpy(pszFilename, szTempFile);  
  101.             }  
  102.         }  
  103.         // 循环到下一个NULL   
  104.         while (*p++);  
  105.     } while (!bFound && *p);  
  106.   
  107.     UnmapViewOfFile(pMem);  
  108.     CloseHandle(hFileMap);  
  109.     printf("File path is %s/n", pszFilename);  
  110.     return TRUE;  
  111. }  
  112.   
  113. /* ************************************ 
  114. * int main() 
  115. * 功能    查找第一个目录中第一个txt文件 
  116. *       打开文件,并根据文件句柄获得文件路径。 
  117. * 参数    未使用 
  118. * 返回值0表示成功,表示失败。 
  119. **************************************/  
  120. int main()  
  121. {  
  122.     HANDLE hFile;  
  123.     HANDLE hFind;  
  124.     WIN32_FIND_DATA wfd;  
  125.     hFind = FindFirstFile("*.txt",&wfd);  
  126.     if(hFind == INVALID_HANDLE_VALUE)  
  127.     {  
  128.         printf("can not find a file");  
  129.         return 1;  
  130.     }  
  131.     //CloseHandle(hFind);   
  132.     printf("find %s at current dir/n",wfd.cFileName);  
  133.     hFile = CreateFile(wfd.cFileName,   
  134.         GENERIC_READ | GENERIC_WRITE,  
  135.         0,   
  136.         NULL,  
  137.         OPEN_EXISTING,   
  138.         FILE_ATTRIBUTE_NORMAL,   
  139.         NULL);  
  140.     if(hFile == INVALID_HANDLE_VALUE)  
  141.     {  
  142.         printf("create file error, %d",GetLastError());  
  143.     }  
  144.     else  
  145.     {  
  146.         GetFileNameFromHandle(hFile) ;  
  147.     }  
  148.     CloseHandle(hFile);  
  149.     return 0;  
  150. }  

 

 

仅收录该书籍以供学习和讨论 包含pdf书籍及经过验证的示例 执行demo中的示例方式 在编译环境下进入demo目录,执行nmake命令在bin目录下生成可执行文件 注:demo无注释,对应书本中部分示例。 目录 第1 Windows应用程序开发入门 1 1.1 第一个实例程序 1 1.1.1 start.exe 1 1.1.2 Windows API 2 1.1.3 程序入口函数 2 1.1.4 start.c代码分析 2 1.2 编译代码 3 1.2.1 安装Visual Studio 3 1.2.2 安装Microsoft Platform SDK 4 1.2.3 集成Microsoft Platform SDK与Visual C++速成版 5 1.2.4 Vista SDK与Visual Studio 2008 6 1.2.5 Visual Studio专业版或团队系统版 7 1.2.6 使用图形化IDE建立工程、进行编译 7 1.2.7 “解决方案”与“工程” 8 1.2.8 使用命令行工具编译 8 第2 Windows API概要 10 2.1 Windows数据类型 10 2.1.1 Windows数据类型示例 10 2.1.2 Windows数据类型与标准C数据类型的关系 14 2.1.3 Windows数据类型与Windows API 14 2.1.4 Windows中的数据结构 15 2.2 Windows API的功能分类 15 2.2.1 系统基本服务 15 2.2.2 系统管理 17 2.2.3 用户界面 17 2.2.4 图像和多媒体 20 2.2.5 网络 20 2.2.6 系统安全 20 2.2.7 其他功能 21 2.3 Windows API核心DLL 21 2.3.1 Kernel32.dll 21 2.3.2 User32.dll 21 2.3.3 Gdi32.dll 22 2.3.4 标准C函数 22 2.3.5 其他Dll 22 2.4 Unicode和多字节 22 2.4.1 W版本和A版本的API 24 2.4.2 Unicode与ASCII的转换 24 2.5 对Windows程序设计规范的建议 25 第3 开发工具配置与使用 26 3.1 使用Visual C/C++编译链接工具 26 3.1.1 编译器cl.exe 27 3.1.2 资源编译器rc.exe 31 3.1.3 链接器link.exe 32 3.1.4 其他工具 38 3.1.5 编译链接工具依赖的环境变量 39 3.1.6 示例:使用/D选项进行条件编译 42 3.2 使用Platform SDK 43 3.2.1 Platform SDK的目录结构与功能 43 3.2.2 为编译链接工具设置环境变量 45 3.2.3 Platform SDK工具集 46 3.2.4 Windows Vista SDK 48 3.3 编写Makefile 48 3.3.1 使用nmake.exe构建工程 48 3.3.2 Makefile实例 50 3.3.3 注释 50 3.3.4 宏 50 3.3.5 描述块:目标、依赖项和命令 53 3.3.6 makefile预处理 55 3.3.7 在Platform SDK的基础上使用nmake 56 3.4 使用WinDbg调试 57 3.4.1 安装WinDbg 57 3.4.2 编译可调试的程序 58 3.4.3 WinDbg命令 59 3.4.4 调试过程演示 59 3.5 集成开发环境 Visual Studio 62 3.5.1 工程类型选择与配置 62 3.5.2 Visual Studio快捷方式 64 3.5.3 生成项目 64 3.5.4 调试 65 3.5.5 选项与设置 65 3.6 开发环境配置总结 66 第4 文件系统 67 4.1 概述 67 4.1.1 文件系统的基本概念 67 4.1.2 文件系统主要API 68 4.2 磁盘和驱动器管理 70 4.2.1 遍历卷并获取属性 70 4.2.2 操作驱动器挂载点 76 4.2.3 判断光驱中是否有光盘 81 4.2.4 获取磁盘分区的总容量、空闲容量、簇、扇区信息 83 4.3 文件和目录管理 86 4.3.1 删除、复制、重命名、移动文件 87 4.3.2 创建、打开、读写文件,获取文件大小 90 4.3.3 创建目录 96 4.3.4 获取程序所在的目录、程序模块路径,获取和设置当前目录 97 4.3.5 查找文件、遍历指定目录下的文件和子目录 100 4.3.6 递归遍历目录树 103 4.3.7 获取、设置文件属性和时间 105 4.4 内存映射文件 110 4.4.1 使用Mapping File提高文件读写的效率 110 4.4.2 通过Mapping File在进程间传递和共享数据 115 4.4.3 通过文件句柄获得文件路径 118 4.5 总结 121 第5 内存管理 122 5.1 Windows内存管理原理 122 5.1.1 基本概念 122 5.1.2 分页与分段内存管理、内存映射与地址转换 123 5.1.3 进程的内存空间 125 5.1.4 虚拟内存布局、内存的分工、堆与栈 127 5.1.5 内存的保护属性和存取权限 127 5.1.6 本API列表 127 5.2 堆管理 129 5.2.1 获取堆句柄、分配与再分配堆 129 5.2.2 获取堆中内存块的大小信息 133 5.2.3 释放内存、销毁堆 134 5.3 全局(Global)和局部(Local)内存管理 136 5.3.1 Global函数 136 5.3.2 Local函数 137 5.3.3 使用全局和局部函数分配和释放内存、改变内存块属性 137 5.4 虚拟内存管理 138 5.4.1 虚拟地址空间与内存分页 139 5.4.2 分配和释放可读可写的虚拟内存页面 139 5.4.3 修改内存页面状态和保护属性、将页面锁定在物理内存中 142 5.4.4 管理其他进程的虚拟内存 143 5.5 内存操作与内存信息管理 144 5.5.1 复制、填充、移动、清零内存块、防止缓冲区溢出 144 5.5.2 获得当前系统内存使用情况 146 5.5.3 判断内存指针的可用性 147 5.6 各种内存分配方式的关系与比较 148 5.6.1 标准C内存管理函数Windows内存管理API的关系 149 5.6.2 功能性区别 149 5.6.3 效率的区别 149 第6 进程、线程和模块 150 6.1 基本概念 150 6.1.1 应用程序与进程 150 6.1.2 控制台应用程序与图形用户界面应用程序 151 6.1.3 动态链接库、模块 151 6.1.4 线程、纤程与作业 152 6.1.5 权限与优先级 153 6.2 进程管理 153 6.2.1 创建进程、获取进程相关信息、获取启动参数 153 6.2.2 编写控制台程序和图形用户界面应用程序 158 6.2.3 获取和设置环境变量 158 6.3 线程、纤程 162 6.3.1 创建线程、退出线程、获取线程信息 162 6.3.2 挂起、恢复、切换、终止线程 164 6.3.3 创建远程线程、将代码注入其他进程中执行 167 6.3.4 创建纤程、删除纤程、调度纤程 170 6.3.5 纤程与线程的互相转换 171 6.4 进程状态信息 176 6.4.1 PS API与Tool help API 176 6.4.2 遍历系统中的进程 178 6.4.3 列举进程的模块、线程 182 6.4.4 进程的堆使用、内存占用、虚拟内存大小,页面错误情况 184 6.5 动态链接库 185 6.5.1 加载、释放DLL、通过句柄获取DLL相关信息 186 6.5.2 编写动态链接库、导出函数 186 6.5.3 创建动态链接库工程,配置DLL编译链接选项 188 6.5.4 运行时动态获取DLL导出函数地址并调用 189 6.5.5 声明导出函数、创建lib库,为其他模块提供导入表调用接口 190 6.5.6 通过构建导入表调用DLL导出函数 191 第7 线程同步 192 7.1 基本原理 192 7.1.1 线程同步的过程 193 7.1.2 同步对象 193 7.1.3 等待函数 193 7.2 同步对象示例 194 7.2.1 使用事件对象(Event) 194 7.2.2 使用互斥对象(Mutex) 199 7.2.3 使用信号量控制访问共享数据的线程数量 202 7.2.4 使用可等待计时器(Timer) 206 7.3 等待进程和线程的执行完成 209 第8 服务 210 8.1 基本概念 210 8.1.1 服务控制器(SCM) 211 8.1.2 服务程序 211 8.1.3 服务控制管理程序 211 8.1.4 系统服务管理工具 211 8.1.5 服务的属性 211 8.2 编写服务程序 212 8.2.1 入口函数 212 8.2.2 服务主函数 212 8.2.3 控制处理函数 213 8.3 实现对服务的控制和管理 216 8.3.1 创建、删除服务 216 8.3.2 启动、停止服务,向服务发送控制请求 219 8.3.3 管理服务状态、配置服务、服务的依赖关系 222 第9 图形用户界面 229 9.1 字符界面程序 229 9.1.1 基本概念 230 9.1.2 控制台读写 231 9.1.3 控制台字体、颜色等属性,操作屏幕缓存 234 9.1.4 控制台事件 244 9.2 图形用户界面:基本概念 246 9.2.1 窗口 246 9.2.2 窗口类 246 9.2.3 消息和消息处理函数 247 9.2.4 控件 247 9.2.5 资源 248 9.2.6 对话框 248 9.3 图形用户界面:窗口 248 9.3.1 注册窗口类 249 9.3.2 创建窗口 251 9.3.3 窗口消息处理函数 253 9.3.4 窗口属性、位置和大小 256 9.3.5 窗口显示方式 257 9.3.6 线程消息队列和消息循环 258 9.4 图形用户界面:控件 258 9.4.1 Tree View控件 258 9.4.2 为Tree View控件增加节点 260 9.4.3 Tree View右键菜单 262 9.4.4 List View控件 263 9.4.5 为List View控件增加分栏 265 9.4.6 为List View控件增加项 266 9.4.7 文本框控件 267 9.4.8 为文本框控件设置文字 268 9.5 界面资源 269 9.5.1 资源脚本(.rc) 269 9.5.2 资源ID定义和头文件 272 9.5.3 在程序中使用资源 273 9.6 菜单 273 9.6.1 菜单资源和菜单句柄 273 9.6.2 动态增加、删除、设置菜单及菜单项 274 9.6.3 菜单消息处理 274 9.7 对话框 275 9.7.1 创建对话框 275 9.7.2 对话框消息处理函数 276 第10 系统信息的管理 277 10.1 Windows系统信息 277 10.1.1 获取系统版本 277 10.1.2 获取计算机硬件信息 279 10.1.3 获取系统目录等信息 281 10.1.4 用户名、计算机名、域名 282 10.1.5 处理系统颜色信息、尺度信息等 284 10.1.6 鼠标、键盘等外设信息 285 10.2 时间信息 286 10.2.1 设置、获取系统时间 286 10.2.2 获取开机至现在持续的时间 287 10.2.3 文件时间与系统时间的转换 287 10.3 注册表 288 10.3.1 注册表的作用及组织形式 288 10.3.2 键、子键、键属性及键值的相关操作 289 10.3.3 列举注册表项及键值 292 10.3.4 通过注册表设置一个自启动的程序 293 10.3.5 设置随程序启动而启动的调试器(任何程序) 294 10.3.6 指定程序崩溃实时调试器 294 第11 进程间通信 295 11.1 邮槽(MailSlot) 295 11.1.1 创建邮槽、从邮槽中读取消息 296 11.1.2 通过邮槽发送消息 299 11.2 管道(Pipe) 300 11.2.1 创建命名管道 300 11.2.2 管道监听 302 11.2.3 使用异步I/O进行读写 303 11.2.4 关闭管道实例 307 11.2.5 客户端 307 11.3 剪贴板 310 11.3.1 获取、设置剪贴板数据 310 11.3.2 监视剪贴板 317 11.3.3 剪贴板数据格式 325 11.4 数据复制消息(WM_COPYDATA) 327 11.4.1 数据发送端 327 11.4.2 数据接收端 330 11.5 其他进程间通信方式 332 11.5.1 动态数据交换(DDE)和网络动态数据交换(NDDE) 332 11.5.2 通过File Mapping在进程间共享数据 333 11.5.3 Windows Socket 333 第12 Windows Shell程序设计 334 12.1 Windows Shell目录管理 335 12.1.1 Shell对目录和文件的管理形式 335 12.1.2 “我的文档”等特殊目录相关操作 335 12.1.3 绑定、遍历、属性获取 337 12.1.4 浏览文件对话框 339 12.2 文件协助(File Associations) 340 12.2.1 文件类型相关注册表键值 340 12.2.2 为文件指定默认打开程序 341 12.2.3 定制文件类型的图标 342 12.3 Shell扩展 343 12.3.1 对象及概念 343 12.3.2 CLSID,处理例程的GUID 344 12.3.3 注册Shell扩展 345 12.3.4 COM程序开发基础 346 12.3.5 编写Handler程序 346 12.3.6 Shell扩展程序的调试 362 12.3.7 总结 363 12.4 任务栏通知区域(Tray)图标 363 12.4.1 创建图标窗口 364 12.4.2 创建图标和图标菜单 367 12.4.3 最小化主窗口到通知区域 370 12.4.4 弹出气泡通知 372 12.4.5 动态图标 374 12.4.6 其他功能 376 第13 Windows GDI 379 13.1 GDI编程接口概述 379 13.1.1 Windows GDI的功能 379 13.1.2 链接库与头文件 380 13.2 设备上下文(DC)、输出操作与图形对象 380 13.2.1 设备上下文类型与关联设备 380 13.2.2 图形对象的作用及与DC的关系 380 13.2.3 各类图形对象的具体属性与作用 383 13.2.4 绘制、填充、写入等图形输出操作 384 13.2.5 修剪与坐标变换 385 13.2.6 设备上下文的图形模式 385 13.3 一个最简单的GDI程序 386 13.3.1 示例 386 13.3.2 DC的操作 387 13.3.3 颜色的表示 388 13.3.4 图形对象:画刷和画笔 389 13.3.5 输出操作:绘制图形和线条 390 13.4 文字和字体 391 13.4.1 选择、设置字体 393 13.4.2 选择字体图形对象 394 13.4.3 文字的颜色 394 13.4.4 输出文字 395 13.4.5 DC图形模式设置 395 13.4.6 遍历字体 396 13.4.7 为系统安装、删除字体文件 398 13.5 绘制线条 398 13.5.1 选择画笔对象 399 13.5.2 直线 399 13.5.3 绘制任意曲线 399 13.5.4 跟踪鼠标轨迹 399 13.5.5 弧线 405 13.6 绘制图形 405 13.6.1 填充颜色与边缘勾勒 406 13.6.2 绘制矩形、椭圆、圆角矩形 406 13.6.3 椭圆弓形和椭圆扇形 411 13.6.4 多边形 411 13.6.5 RECT结构及对RECT的操作 412 13.7 位图操作 414 13.7.1 截取屏幕、保存位图文件 414 13.7.2 将位图显示在界面上 419 13.8 区域(Regions)、路径(Paths)与修剪(Clip)操作 422 13.8.1 区域的创建及形状、位置等属性 422 13.8.2 区域边沿、区域填充、反转与勾勒操作 423 13.8.3 组合、比较、移动等操作 426 13.8.4 点击测试(Hit Testing) 427 13.8.5 路径的创建与操作 431 13.8.6 路径转换为区域 432 13.8.7 使用区域和路径进行修剪操作,限制输出 432 13.9 坐标变换 438 13.9.1 缩放 439 13.9.2 旋转 440 13.10 调色板 440 第14 网络通信与配置 443 14.1 Socket通信 444 14.1.1 客户端 444 14.1.2 服务端 449 14.1.3 处理并发的客户端连接 455 14.1.4 网络通信的异步I/O模式 456 14.2 IP Helper 456 第15 程序安装与设置 463 15.1 创建cab文件 463 15.1.1 makecab.exe 463 15.1.2 压缩多个文件 464 15.1.3 Cabinet软件开发工具包(CABSDK) 466 15.2 编写INF文件 466 15.2.1 INF文件格式 466 15.2.2 Install节 468 15.2.3 CopyFiles和AddReg等安装过程 468 15.2.4 源路径和目的路径 469 15.2.5 字符串表 469 15.3 安装程序setup.exe的编号 469 15.4 使用msi文件进行安装 472 15.4.1 Windows Installer Service 472 15.4.2 msi文件的创建与修改工具orca.exe 474 15.4.3 准备工作 475 15.4.4 编辑表组 475 第16 设备驱动管理与内核通信 476 16.1 设备管理 476 16.1.1 列举设备接口 477 16.1.2 监控设备的加载和卸载 483 16.2 I/O控制、内核通信 488 16.2.1 加载驱动程序 488 16.2.2 控制驱动程序、与驱动程序进行通信 495 16.3 编写设备驱动程序 498 16.3.1 驱动程序开发包:DDK 499 16.3.2 开发驱动程序 499 16.4 I/O模式,同步与异步 504 第17 用户、认证和对象安全 506 17.1 基本概念 506 17.1.1 访问令牌、权限和用户标识 506 17.1.2 进程的系统操作权限 507 17.1.3 安全对象 508 17.1.4 访问控制列表(ACL) 508 17.2 安全机制程序示例 509 17.2.1 列举进程访问令牌内容和权限 509 17.2.2 修改进程的权限 514 17.2.3 列举安全对象的安全描述符 515 17.2.4 修改安全描述符 521 17.3 用户 522 17.3.1 创建用户 522 17.3.2 用户组 523 17.3.3 删除用户 525 17.3.4 列举用户和用户组、获取用户信息 525 第18 Windows API的内部原理 532 18.1 关于API的补充说明 532 18.1.1 Windows API的版本演进和Vista新增API 532 18.1.2 64位操作系统的接口 533 18.2 Windows系统中的对象封装 533 18.2.1 什么是对象 534 18.2.2 面向对象的思想 534 18.2.3 Windows系统中的对象:内核对象、GDI对象等 534 18.3 Windows程序设计参考:文档资源与样例代码 534 18.3.1 SDK文档和MSDN 534 18.3.2 SDK示例代码 535 18.4 x86平台程序函数调用原理 535 18.4.1 函数调用的真实过程 535 18.4.2 函数调用约定 539 18.4.3 为什么通过参数返回数据时只能使用指针 540 18.4.4 缓冲区溢出 540 18.4.5 程序运行错误的调试技巧 540 18.5 可执行程序结构与API函数接口内部机理 541 18.5.1 Windows可执行程序结构 541 18.5.2 导入表、导出表、动态链接 543 18.5.3 NTDLL.DLL、NATIVE API和SSDT 544 18.5.4 API HOOK 546 18.6 发布程序 546 18.6.1 合理选择编译链接选项 546 18.6.2 构建到指定路径 546 18.7 模块化,向Windows API学习接口定义 547 18.7.1 lib文件 547 18.7.2 头文件 547 18.7.3 为第三方应用软件提供SDK 547
第1 Windows应用程序开发入门..........................................................................................16 1.1 第一个实例程序............................................................................................................16 1.1.1 sta rt.exe..............................................................................................................16 1.1.2 Windows API......................................................................................................17 1.1.3 程序入口函数.....................................................................................................17 1.1.4 start.c代码分析...................................................................................................17 1.2 编译代码........................................................................................................................18 1.2.1 安装Visual Studio...............................................................................................18 1.2.2 安装Microsoft Platform SDK.............................................................................19 1.2.3 集成Microsoft Platform SDK与Visual C++速成版...........................................20 1.2.4 Vista SDK与Visual Studi0 2008.........................................................................21 1.2.5 Visual Studio专业版或团队系统版...................................................................22 1.2.6 使用图形化IDE建立工程、进行编译..............................................................22 1.2.7 “解决方案”与“工程”..........................................................................................23 1.2.8 使用命令行工具编译.........................................................................................23 第2 Windows API概要..........................................................................................................24 2.1 Windows数据类型.........................................................................................................24 2.1.1 Windows数据类型示例......................................................................................25 2.1.2 Windows数据类型与标准C数据类型的关系...................................................28 2.1.3 Windows数据类型与Windows API...................................................................28 2.1.4 Windows中的数据结构......................................................................................29 2.2 Windows API的功能分类.............................................................................................29 2.2.1 系统基本服务.....................................................................................................29 2.2.2 系统管理.............................................................................................................31 2.2.3 用户界面.............................................................................................................31 2.2.4 图像和多媒体.....................................................................................................34 2.2.5 网络.....................................................................................................................34 2.2.6 系统安全.............................................................................................................34 2.2.7 其他功能.............................................................................................................35 2.3 Windows API核心DLL..................................................................................................35 2.3.1 Kerne132.dll........................................................................................................35 2.3.2 User32.dll............................................................................................................36 2.3.3 Gdi32.dll.............................................................................................................36 2.3.4 标准C函数..........................................................................................................36 2.3.5 其他Dll................................................................................................................36 2.4 Unicode和多字节..........................................................................................................36 2.4.1 W版本和A版本的API........................................................................................38 2.4.2 Unicode与ASGII的转换.....................................................................................39 2.5 对Windows程序设计规范的建议.................................................................................39 第3开发工具配置与使用.....................................................................................................41 3.1 使用Visual C/C++编译链接工具...............................................................................41 3.1.1 编译器cl.exe.......................................................................................................41 3.1.2 资源编译器rc.exe...............................................................................................46 3.1.3 链接器link.exe....................................................................................................47 3.1.4 其他工具.............................................................................................................53 3.1.5 编译链接工具依赖的环境变量.........................................................................54 3.1.6 示例:使用/D选项进行条件编译.....................................................................57 3.2 使用Platform SDK.........................................................................................................58 3.2.1 Platform SDK的目录结构与功能......................................................................58 3.2.2 为编译链接工具设置环境变量.........................................................................59 3.2.3 Platform SDK工具集..........................................................................................61 3.2.4 Windows Vista SDK............................................................................................63 3.3 编写Makefile.................................................................................................................63 3.3.1 使用nmake.exe构建工程....................................................................................63 3.3.2 Makefile实例......................................................................................................65 3.3.3 注释.....................................................................................................................65 3.3.4 宏.........................................................................................................................66 3.3.5 描述块:目标、依赖项和命令.........................................................................68 3.3.6 makefile预处理...................................................................................................69 3.3.7 在Platform SDK的基础上使用nmake...............................................................70 3.4 使用WinDbg调试..........................................................................................................72 3.4.1 安装WinDbg.......................................................................................................72 3.4.2 编译可调试的程序.............................................................................................73 3.4.3 WinDbg命令.......................................................................................................74 3.4.4 调试过程演示.....................................................................................................74 3.5 集成开发环境Visual Studio..........................................................................................77 3.5.1 工程类型选择与配置.........................................................................................77 3.5.2 Visual Studio快捷方式.......................................................................................79 3.5.3 生成项目.............................................................................................................79 3.5.4 调试.....................................................................................................................79 3.5.5 选项与设置.........................................................................................................80 3.6 开发环境配置总结........................................................................................................81 第4文件系统.........................................................................................................................82 4.1 概述...............................................................................................................................82 4.1.1 文件系统的基本概念.........................................................................................82 4.1.2 文件系统主要API..............................................................................................83 4.2 磁盘和驱动器管理........................................................................................................85 4.2.1 遍历卷并获取属性.............................................................................................85 4.2.2 操作驱动器挂载点.............................................................................................91 4.2.3 判断光驱中是否有光盘.....................................................................................96 4.2.4 获取磁盘分区的总容量、空闲容量、簇、扇区信息.....................................98 4.3 文件和目录管理..........................................................................................................101 4.3.1 删除、复制、重命名、移动文件...................................................................102 4.3.2 创建、打开、读写文件,获取文件大小.......................................................105 4.3.3 创建目录...........................................................................................................111 4.3.4 获取程序所在的目录、程序模块路径,获取和设置当前目录...................112 4.3.5 查找文件、遍历指定目录下的文件和子目录...............................................115 4.3.6 递归遍历目录树...............................................................................................118 4.3.7 获取、设置文件属性和时间...........................................................................120 4.4 内存映射文件..............................................................................................................125 4.4.1 使用Mapping File提高文件读写的效率.........................................................125 4.4.2 通过Mapping File在进程间传递和共享数据.................................................130 4.4.3 通过文件句柄获得文件路径...........................................................................133 4.5 总结..............................................................................................................................136 第5内存管理.......................................................................................................................137 5.1 Windows内存管理原理...............................................................................................137 5.1.1 基本概念...........................................................................................................137 5.1.2 分页与分段内存管理、内存映射与地址转换...............................................138 5.1.3 进程的内存空间...............................................................................................140 5.1.4 虚拟内存布局、内存的分工、堆与栈...........................................................142 5.1.5 内存的保护属性和存取权限...........................................................................142 5.1.6 本API列表....................................................................................................142 5.2 堆管理..........................................................................................................................144 5.2.1 获取堆句柄、分配与再分配堆.......................................................................144 5.2.2 获取堆中内存块的大小信息...........................................................................148 5.2.3 释放内存、销毁堆...........................................................................................149 5.3 全局(Global)和局部(Local)内存管理.........................................................................151 5.3.1 Global函数........................................................................................................151 5.3.2 Local函数........................................................................................................152 5.3.3 使用全局和局部函数分配和释放内存、改变内存块属性...........................153 5.4 虚拟内存管理..............................................................................................................154 5.4.1 虚拟地址空间与内存分页...............................................................................154 5.4.2 分配和释放可读可写的虚拟内存页面...........................................................154 5.4.3 修改内存页面状态和保护属性、将页面锁定在物理内存中.......................157 5.4.4 管理其他进程的虚拟内存...............................................................................158 5.5 内存操作与内存信息管理..........................................................................................159 5.5.1 复制充、移动、清零内存块、防止缓冲区溢出...........................................159 5.5.2 获得当前系统内存使用情况...........................................................................161 5.5.3 判断内存指针的可用性...................................................................................162 5.6 各种内存分配方式的关系与比较..............................................................................163 5.6.1 标准C内存管理函数Windows内存管理API的关系...................................163 5.6.2 功能性区别.......................................................................................................164 5.6.3 效率的区别.......................................................................................................164 第6进程、线程和模块.......................................................................................................165 6.1 基本概念......................................................................................................................165 6.1.1 应用程序与进程...............................................................................................165 6.1.2 控制台应用程序与图形用户界面应用程序...................................................166 6.1.3 动态链接库、模块...........................................................................................166 6.1.4 线程、纤程与作业...........................................................................................167 6.1.5 权限与优先级...................................................................................................167 6.2 进程管理......................................................................................................................167 6.2.1 创建进程、获取进程相关信息、获取启动参数...........................................168 6.2.2 编写控制台程序和图形用户界面应用程序...................................................173 6.2.3 获取和设置环境变量.......................................................................................173 6.3 线程、纤程..................................................................................................................176 6.3.1 创建线程、退出线程、获取线程信息...........................................................177 6.3.2 挂起、恢复、切换、终止线程.......................................................................179 6.3.3 创建远程线程、将代码注入其他进程中执行...............................................182 6.3.4 创建纤程、删除纤程、调度纤程...................................................................185 6.3.5 纤程与线程的互相转换...................................................................................186 6.4 进程状态信息..............................................................................................................191 6.4.1 PS API与Tool help API.....................................................................................191 6.4.2 遍历系统中的进程...........................................................................................193 6.4.3 列举进程的模块、线程...................................................................................197 6.4.4 进程的堆使用、内存占用、虚拟内存大小,页面错误情况.......................199 6.5 动态链接库..................................................................................................................200 6.5.1 加载、释放DLL、通过句柄获取DLL相关信息............................................201 6.5.2 编写动态链接库、导出函数...........................................................................201 6.5.3 创建动态链接库工程,配置DLL编译链接选项...........................................203 6.5.4 运行时动态获取DLL导出函数地址并调用...................................................204 6.5.5 声明导出函数、创建lib库,为其他模块提供导入表调用接口...................205 6.5.6 通过构建导入表调用DLL导出函数...............................................................206 第7线程同步.......................................................................................................................207 7.1 基本原理......................................................................................................................207 7.1.1 线程同步的过程...............................................................................................207 7.1.2 同步对象...........................................................................................................208 7.1.3 等待函数...........................................................................................................208 7.2 同步对象示例..............................................................................................................209 7.2.1 使用事件对象(Event).......................................................................................209 7.2.2 使用互斥对象(Mutex)......................................................................................214 7.2.3 使用信号量控制访问共享数据的线程数量...................................................217 7.2.4 使用可等待计时器(Timer)...............................................................................221 7.3 等待进程和线程的执行完成......................................................................................224 第8服务...............................................................................................................................225 8.1 基本概念......................................................................................................................225 8.1.1 服务控制器(SCM)............................................................................................225 8.1.2 服务程序...........................................................................................................226 8.1.3 服务控制管理程序...........................................................................................226 8.1.4 系统服务管理工具...........................................................................................226 8.1.5 服务的属性.......................................................................................................226 8.2 编写服务程序..............................................................................................................227 8.2.1 入口函数...........................................................................................................227 8.2.2 服务主函数.......................................................................................................227 8.2.3 控制处理函数...................................................................................................228 8.3 实现对服务的控制和管理..........................................................................................231 8.3.1 创建、删除服务...............................................................................................231 8.3.2 启动、停止服务,向服务发送控制请求.......................................................234 8.3.3 管理服务状态、配置服务、服务的依赖关系...............................................237 第9图形用户界面...............................................................................................................244 9.1 字符界面程序..............................................................................................................244 9.1.1 基本概念...........................................................................................................244 9.1.2 控制台读写.......................................................................................................246 9.1.3 控制台字体、颜色等属性,操作屏幕缓存...................................................249 9.1.4 控制台事件.......................................................................................................259 9.2 图形用户界面:基本概念..........................................................................................262 9.2.1 窗口...................................................................................................................262 9.2.2 窗口类...............................................................................................................263 9.2.3 消息和消息处理函数.......................................................................................263 9.2.4 控件...................................................................................................................263 9.2.5 资源...................................................................................................................264 9.2.6 对话框...............................................................................................................264 9.3 图形用户界面:窗口..................................................................................................264 9.3.1 注册窗口类.......................................................................................................266 9.3.2 创建窗口...........................................................................................................267 9.3.3 窗口消息处理函数...........................................................................................269 9.3.4 窗口属性、位置和大小...................................................................................273 9.3.5 窗口显示方式...................................................................................................274 9.3.6.线程消息队列和消息循环...............................................................................274 9.4 图形用户界面:控件..................................................................................................275 9.4.1 Tree View控件..................................................................................................275 9.4.2 为Tree View控件增加节点..............................................................................277 9.4.3 Tree View右键菜单..........................................................................................278 9.4.4 List View控件...................................................................................................280 9.4.5 为List View控件增加分栏...............................................................................282 9.4.6 为List View控件增加项...................................................................................283 9.4.7 文本框控件.......................................................................................................284 9.4.8 为文本框控件设置文字...................................................................................285 9.5 界面资源......................................................................................................................286 9.5.1 资源脚本(.rc).................................................................................................286 9.5.2 资源ID定义和头文件.......................................................................................289 9.5.3 在程序中使用资源...........................................................................................289 9.6 菜单..............................................................................................................................290 9.6.1 菜单资源和菜单句柄.......................................................................................290 9.6.2 动态增加、删除、设置菜单及菜单项...........................................................291 9.6.3 菜单消息处理...................................................................................................292 9.7 对话框..........................................................................................................................292 9.7.1 创建对话框.......................................................................................................292 9.7.2 对话框消息处理函数.......................................................................................293 第10系统信息的管理.........................................................................................................295 10.1 Windows系统信息.....................................................................................................295 10.1.1 获取系统版本.................................................................................................295 10.1.2 获取计算机硬件信息.....................................................................................297 10.1.3 获取系统目录等信息.....................................................................................299 10.1.4 用户名、计算机名、域名.............................................................................300 10.1.5 处理系统颜色信息、尺度信息等.................................................................302 10.1.6 鼠标、键盘等外设信息.................................................................................303 10.2 时间信息....................................................................................................................304 10.2.1 设置、获取系统时间.....................................................................................304 10.2.2 获取开机至现在持续的时间.........................................................................305 10.2.3 文件时间与系统时间的转换.........................................................................305 10.3 注册表........................................................................................................................306 10.3.1 注册表的作用及组织形式.............................................................................306 10.3.2 键、子键、键属性及键值的相关操作.........................................................307 10.3.3 列举注册表项及键值.....................................................................................309 10.3.5 设置随程序启动而启动的调试器(任何程序).........................................312 10.3.6 指定程序崩溃实时调试器.............................................................................312 第11进程间通信.................................................................................................................313 11.1 邮槽( MailSlot ).........................................................................................................313 11.1.1 创建邮槽、从邮槽中读取消息.....................................................................313 11.1.2 通过邮槽发送消息.........................................................................................317 11.2 管道(Pipe)..................................................................................................................318 11.2.1 创建命名管道.................................................................................................318 11.2.2 管道监听.........................................................................................................320 11.2.3 使用异步I/O进行读写....................................................................................321 11.2.4 关闭管道实例.................................................................................................325 11.2.5 客户端.............................................................................................................325 11.3 剪贴板........................................................................................................................328 11.3.1 获取、设置剪贴板数据.................................................................................328 11.3.2 监视剪贴板.....................................................................................................334 11.3.3 剪贴板数据格式.............................................................................................343 11.4 数据复制消息(WM_COPYDATA)...........................................................................345 11.4.1 数据发送端.....................................................................................................345 11.4.2 数据接收端.....................................................................................................348 11.5 其他进程间通信方式................................................................................................350 11.5.1 动态数据交换(DDE)和网络动态数据交换(NDDE).....................................350 11.5.3 Windows Socket..............................................................................................351 第12 Windows Shell程序设计............................................................................................352 12.1 Windows Shell目录管理...........................................................................................352 12.1.1 Shell对目录和文件的管理形式.....................................................................353 12.1.2 “我的文档”等特殊目录相关操作.................................................................353 12.1.3 绑定、遍历、属性获取.................................................................................354 12.1.4 浏览文件对话框.............................................................................................357 12.2 文件协助(File Associations)......................................................................................358 12.2.1 文件类型相关注册表键值.............................................................................359 12.2.2 为文件指定默认打开程序.............................................................................359 12.2.3 定制文件类型的图标.....................................................................................360 12.3 Shell扩展.................................................................................................................361 12.3.1 对象及概念.....................................................................................................361 12.3.2 CLSID,处理例程的GUID...........................................................................362 12.3.3 注册Shell扩展.................................................................................................363 12.3.4 COM程序开发基础........................................................................................364 12.3.5 编写Handler程序............................................................................................364 12.3.6 Shell扩展程序的调试.....................................................................................380 12.3.7 总结.................................................................................................................381 12.4 任务栏通知区域(Tray)图标......................................................................................381 12.4.1 创建图标窗口.................................................................................................382 12.4.2 创建图标和图标菜单.....................................................................................386 12.4.4 弹出气泡通知.................................................................................................391 12.4.5 动态图标.........................................................................................................393 12.4.6 其他功能.........................................................................................................395 第13 Windows GDI.............................................................................................................398 13.1 GDI编程接口概述.....................................................................................................398 13.1.1 Windows GDI的功能......................................................................................398 13.1.2 链接库与头文件.............................................................................................398 13.2 设备上下文(DC)\输出操作与图形对象................................................................398 13.2.1 设备上下文类型与关联设备.........................................................................399 13.2.2 图形对象的作用及与DC的关系...................................................................399 13.2.3 各类图形对象的具体属性与作用.................................................................401 13.2.4 绘制、填充、写入等图形输出操作.............................................................402 13.2.5 修剪与坐标变换.............................................................................................403 13.2.6 设备上下文的图形模式.................................................................................403 13.3 一个最简单的GDI程序.............................................................................................404 13.3.1 示例.................................................................................................................404 13.3.2 DC的操作.....................................................................................................406 13.3.3 颜色的表示.....................................................................................................407 13.3.4 图形对象:画刷和画笔.................................................................................407 13.3.5 输出操作:绘制图形和线条.........................................................................409 13.4 文字和字体................................................................................................................409 13.4.1 选择、设置字体.............................................................................................412 13.4.2 选择字体图形对象.........................................................................................413 13.4.3 文字的颜色.....................................................................................................413 13.4.4 输出文字.........................................................................................................413 13.4.5 DC图形模式设置...........................................................................................414 13.4.6 遍历字体.........................................................................................................415 13.4.7 为系统安装、删除字体文件.........................................................................417 13.5 绘制线条....................................................................................................................417 13.5.1 选择画笔对象.................................................................................................417 13.5.2 直线.................................................................................................................418 13.5.3 绘制任意曲线.................................................................................................418 13.5.4 跟踪鼠标轨迹.................................................................................................418 13.5.5 弧线.................................................................................................................424 13.6 绘制图形....................................................................................................................424 13.6.1 填充颜色与边缘勾勒.....................................................................................425 13.6.2 绘制矩形、椭圆、圆角矩形.........................................................................425 13.6.3 椭圆弓形和椭圆扇形.....................................................................................431 13.6.4 多边形.............................................................................................................431 13.6.5 REGT结构及对RECT的操作........................................................................432 13.7 位图操作....................................................................................................................434 13.7.1 截取屏幕、保存位图文件.............................................................................434 13.7.2 将位图显示在界面上.....................................................................................439 13.8 区域(Regions)、路径(Paths)与修剪(Clip)操作.......................................................442 13.8.1 区域的创建及形状、位置等属性.................................................................442 13.8.2 区域边沿、区域填充、反转与勾勒操作.....................................................443 13.8.3 组合、比较、移动等操作.............................................................................446 13.8.4 点击测试(Hit Testing)....................................................................................447 13.8.5 路径的创建与操作.........................................................................................451 13.8.6 路径转换为区域.............................................................................................452 13.8.7 使用区域和路径进行修剪操作,限制输出.................................................452 13.9 坐标变换....................................................................................................................458 13.9.1 缩放.................................................................................................................459 13.9.2 旋转.................................................................................................................460 13.10 调色板......................................................................................................................460 第14网络通信与配置.........................................................................................................463 14.1 Socket通信.................................................................................................................463 14.1.1 客户端.............................................................................................................464 14.1.2 服务端.............................................................................................................469 14.1.3 处理并发的客户端连接.................................................................................475 14.1.4 网络通信的异步I/O模式................................................................................476 14.2 IP Helper....................................................................................................................476 第15程序安装与设置.........................................................................................................483 15.1.1 makecab.exe....................................................................................................483 15.1.2 压缩多个文件.................................................................................................484 15.1.3 Cabinet软件开发工具包(CABSDK)..............................................................485 15.2 编写INF文件.............................................................................................................486 15.2.1 INF文件格式..................................................................................................486 15.2.2 Install节...........................................................................................................488 15.2.3 CopyFiles和AddReg等安装过程...................................................................488 15.2.4 源路径和目的路径.........................................................................................489 15.2.5 字符串表.........................................................................................................489 15.3 安装程序setup.exe的编号.........................................................................................489 15.4 使用msi文件进行安装..............................................................................................493 15.4.1 Windows Installer Service...............................................................................493 15.4.2 msi文件的创建与修改工具orca.exe..............................................................495 15.4.3 准备工作.........................................................................................................496 15.4.4 编辑表组.........................................................................................................496 第16设备驱动管理与内核通信.........................................................................................497 16.1 设备管理....................................................................................................................497 16.1.1 列举设备接口.................................................................................................497 16.1.2 监控设备的加载和卸载.................................................................................504 16.2 I/o控制、内核通信...................................................................................................509 16.2.1 加载驱动程序.................................................................................................509 16.2.2 控制驱动程序、与驱动程序进行通信.........................................................516 16.3 编写设备驱动程序....................................................................................................519 16.3.1 驱动程序开发包:DDK................................................................................520 16.4 I/O模式,同步与异步..............................................................................................525 第17用户、认证和对象安全.............................................................................................527 17.1 基本概念....................................................................................................................527 17.1.1 访问令牌、权限和用户标识.........................................................................527 17.1.2 进程的系统操作权限.....................................................................................528 17.1.3 安全对象.........................................................................................................528 17.1.4 访问控制列表(ACL)......................................................................................529 17.2 安全机制程序示例....................................................................................................530 17.2.1 列举进程访问令牌内容和权限.....................................................................530 17.2.2 修改进程的权限.............................................................................................536 17.2.3 列举安全对象的安全描述符.........................................................................537 17.2.4 修改安全描述符.............................................................................................543 17.3 用户............................................................................................................................544 17.3.1 创建用户.........................................................................................................544 17.3.2 用户组.............................................................................................................545 17.3.3 删除用户.........................................................................................................546 17.3.4 列举用户和用户组、获取用户信息.............................................................547 第18 Windows API的内部原理..........................................................................................554 18.1 关于API的补充说明.................................................................................................554 18.1.1 Windows API的版本演进和Vista新增API....................................................554 18.1.2 64位操作系统的接口..................................................................................555 18.2 Windows系统中的对象封装.....................................................................................555 18.2.1 什么是对象.....................................................................................................555 18.2.2 面向对象的思想.............................................................................................555 18.2.3 Windows系统中的对象:内核对象、GDI对象等.......................................556 18.3 WiFidows程序设计参考:文档资源与样例代码....................................................556 18.3.1 SDK文档和MSDN.........................................................................................556 18.3.2 SDK示例代码.................................................................................................556 18.4 x86平台程序函数调用原理.....................................................................................557 18.4.1 函数调用的真实过程.....................................................................................557 18.4.2 函数调用约定.................................................................................................561 18.4.3 为什么通过参数返回数据时只能使用指针.................................................562 18.4.4 缓冲区溢出.....................................................................................................562 18.4.5 程序运行错误的调试技巧.............................................................................562 18.5 可执行程序结构与AIPI函数接口内部机理............................................................563 18.5.1 Windows可执行程序结构..............................................................................563 18.5.2 导入表、导出表、动态链接.........................................................................565 18.5.3 NTDLL.DLL、NATIVE API和SSDT............................................................566 18.5.4 API HOOK......................................................................................................568 18.6 发布程序....................................................................................................................569 18.6.1 合理选择编译链接选项.................................................................................569 18.6.2 构建到指定路径.............................................................................................569 18.7 模块化,向Windows APl学习接口定义..................................................................569 18.7.1 lib文件............................................................................................................569 18.7.2 头文件.............................................................................................................570 18.7.3 为第三方应用软件提供SDK.........................................................................570
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值