月度归档:2008年12月

驱动器和目录 — 逻辑驱动器操作

1.卷标操作
驱动器创建,修改,删除卷标都可以使用SetVolumeLabel函数

szPath db 'c:',0
szVolume db 'System',0
invoke SetVolumeLabel,addr szPath,szVolume

szPath:指出了要设置卷标的逻辑驱动器的根目录
szVolume:指向包含卷标字符串的缓冲区
删除卷标的二种方法

szPath db 'c:',0
szVolume db 0
invoke SetVolumeLabel,addr szPath,szVolume

szPath db 'c:',0
invoke SetVolumeLabel,addr szPath,NULL

如果函数执行成功返回值是TRUE,否则返回FALSE

2.逻辑驱动器的检测
检测系统中当前存在多少个逻辑驱动器可以使用GetLogicalDrives函数,它没有输入参数,它返回一个32位整数,用其中的每一位代表是否存在一个逻辑驱动器.由于系统中可用的盘符公有26个(A~Z),所以用第0到第25位表示A:~Z:

如果认为认为上面的函数做位测试比较麻烦也可以使用GetLogicalDriveStrings,这个函数返回字符串类型的逻辑驱动器列表:

invoke GetLogicalDriverStrings,dwBufferSize,lpBuffer

lpBuffer:指向一个缓冲区,函数在这里返回'A:',0,'B:',0 格式的字符串
dwBufferSize:指出缓存区的大小,如果缓冲区不够大,后面的数据会被截尾

检测驱动器类型的工作可以用GetDriveType函数来完成

szPath db 'c:',0
invoke GetDriveType,addr szPath

szPath指向存放在逻辑驱动器根目录的字符串的缓冲区,函数返回值是驱动器的类型,是下面7个位的一种
0:驱动器类型无法检测
1:指定的根目录不存在
DRIVE_REMOVABLE:可移动介质,如软盘
DRIVE_FIXED:固定盘,如硬盘中的逻辑驱动器
DRIVE_REMOTE:远程驱动器,如网络上映射的驱动器
DRIVE_CDROM:光盘
DRIVE_RAMDISK:内存虚拟盘

如果需要更详细的情况,可以使用GetVolumeInformation函数

invoke GetVolumeInformation,lpRootPathName,lpVolumeNameBuffer,dwVolumeNameSize,lpVolumeSerialNumber,lpMaximumComponentLength,lpFileSystemFlags,lpFileSystemNameBuffer,dwFileSystemNameSize

lpRootPathName:指向需要检测的驱动器根目录字符串,如果是网络驱动器,可以是'\服务器名共享名'
lpVolumeNameBuffer:指向一个字符串缓冲区,用来返回驱动器的卷标,缓冲区长度由dwVolumeNameSize参数指出
lpVolumeSerialNumber:指向一个双字变量,在这里返回逻辑驱动器的序列号,序列号是驱动器被格式化的时候由系统随机产生的一个32位数,它保存在位于驱动器第一个扇区的引导记录中.
lpMaximumComponentLength:指向一个双字变量,在这里返回最大允许的文件名长度,windows中为255
lpFileSystemFlags:指向一个双字变量,在这里返回一些逻辑驱动器的属性标志返回值可能是下列值的组合
FS_CASE_IS_PRESERVED:文件系统保存文件名时保持它的大小写
FS_CASE_SENSITIVE:支持区分大小写的文件名
FS_UNICODE_STORED_ON_DISK:允许存放Unicode格式的文件名
FS_PERSISTENT_ACLS:支持ACL
FS_FILE_COMPRESSION:支持文件压缩
FS_VOL_IS_COMPRESSED:支持卷压缩
lpFileSystemNameBuffer:指向一个字符串缓冲区,用来接收文件系统字符串,类似于'NTFS'或'FAT32'之类的dwFileSystemNameSize指定了这个缓冲区的长度

检测逻辑驱动器剩余空间GetDiskFreeSpace用法如下

invoke GetDiskFreeSpace,lpRootPathName,lpSectorsPerCluster,lpBytesPerSector,lpNumberOfFreeClusters,lpTotalNumberOfClusters

lpRootPathName:指向驱动器根目录字符串
lpSectorsPerCluster:返回每簇的扇区数
lpBytesPerSector:返回每扇区的字节数
lpNumberOfFreeClusters:返回驱动器中未使用的簇的数量
lpTotalNumberOfClusters:返回驱动器中簇的总数

Windows 文件操作 — 其它文件操作

1.拷贝文件
拷贝文使用CopyFile或CopyFileEx

invoke CopyFile,lpExistingFileName,lpNewFileName,bFailIfExists

函数将lpExistingFileName指定文件拷贝为lpNewFileName指定的文件
bFailIfExists指定目标存在时的动作,指定为TRUE,拷贝失败;指定为FALSE则覆盖掉原来的文件,拷贝出来的新文件的属性和原来文件的属性一样
CopyFileEx函数可以完成同样的功能,只不过函数可以指定一个回调函数.

2.移动文件
移动文件使用MoveFile或MoveFileEx

invoke MoveFile,lpExistingFileName,lpNewFileName

将lpExistingFileName指定的文件移动到lpNewFileName指定的目标位置,文件名可以同时改变或不改变,目标文件必须不存在,否则函数调用失败.当函数执行成功的时候返回非0值,否则函数返回0
注意:MoveFile函数可以移动文件或目录.当移动一个文件时,源文件和目标文件可以处于不同的驱动器上
当移动对象是一个文件夹时,源目录与目标目录必须在一个驱动器上

invoke MoveFileEx,lpExistingFileName,lpNewFileName,dwFlags

MoveFileEx函数增加了一个dwFlags参数来时行移动控制,参数可以是下面取值的组合
MOVEFILE_COPY_ALLOWED:允许拷贝数据,如果不指定,文件不能移动到不同的驱动器上,不能与REBOOT同时使用
MOVEFILE_DELAY_UNTIL_REBOOT:在Winnt上执行时,函数在下一次启动时再进行移动操作
MOVEFILE_REPLACE_EXISTING:如果目标存在,将它替换掉(与MoveFile相比的优点)
MoveFileEx还有个特殊用法

invoke MoveFileEx,lpExistingFileName,NULL,MOVEFILE_DELAY_UNTIL_REBOOT

将在下一次启动时将lpExistingFileName指定的文件删除(Win95不支持)

3.删除文件
删除文件使用DeleteFile函数

invoke DeleteFile,lpFileName

lpFileName指向一个包含要删除文件名的字符串.在Win95下执行时,可以删除打开状态的文件,在NT下执行,不能对一个打开的文件进行删除.

Windows 文件操作 — 文件属性

1.Win32的文件函数可以操作多种对象,用GetFileType函数可以得到操作对象的类型.

invoke GetFileType,hFile

该函数返回值有4种
FILE_TYPE_UNKNOWN 文件类型未知
FILE_TYPE_DISK 磁盘文件
FILE_TYPE_CHAR 字符设备
FILE_TYPE_PIPE 管道

2.获取文件长度
使用GetFileSize函数

invoke GetFileSize,hFile,lpFileSizeHigh

lpFileSizeHigh指向一个用来接收高32位长度的变量,一般设置为NULL,长度的低32位在函数的返回值中返回,GetFileSize返回的是当前长度

3.获取和修改文件日期
获取文件日期使用GetFileTime

invoke GetFileTime,hFile,lpCreationTime,lpLastAccessTime,lpLastWriteTime

hFile:操作文件句柄
lpCreationTime:创建日期
lpLastAccessTime:最后存取日期
lpLastWriteTime:最后写入日期
如果不需要某个日期可将它设置为NULL
返回的日期是个FILETIME 结构

FILETIME STRUCT
dwLowDateTime DWORD ? ;文件日期低32位
dwHighDateTime DWORD ? ;文件日期高32位
FILETIME ENDS

这个结构中无法直接得到日期的年月日时分秒等数据.转换FILETIME为SYSTEMTIME结构,使用FileTimeToSystemTime进行转换

invoke FileTimeToSystemTime,lpFileTime,lpSystemTime

设置日期

invoke SetFileTime,hFile,lpCreationTime,lpLastAccessTime,lpLastWriteTime

填写FILETIME结构的时候,最简便的方法

invoke SystemTimeToFileTime,lpSystemTime,lpFileTime

4.获取和修改文件属性
创建文件是,可以在CreateFile的dwFlagsAndAttributes参数指定,也可以在以后用SetFileAttributes修改属性

invoke SetFileAttributes,lpFileName,dwFileAttributes

调用SetFileAttributes不需要打开文件上,只要指定全路径的文件名就可以了
dwFileAttributes与dwFlagsAndAttributes的参数是一样的

获取文件的只读,隐含与系统等属性,可以使用GetFileAttributes

invoke GetFileAttributes,lpFimeName

如果函数执行失败返回-1 成功返回文件的属性

Windows 文件操作 — 查找文件

开始查找文件,首先使用FindFirstFile函数,如果函数执行成功,返回一个句柄hFindFile来对应这个寻找操作,接下来可以利用这个句柄循环调用FindNextFile继续查找其它文件,直到FindNextFile返回失败为止.最后关闭hFindFile句柄.一般查找文件的代码结构:

invoke FindFirstFile,lpFindFile,lpFindFileDate
.if eax != INVALID_HANDLE_VALUE
mov hFindFile,eax
.repeat
;处理本次找到的文件
invoke FindNextFile,hFindFile,addr lpFindFileData
.until eax==FALSE
invoke FindClose,hFindFile
.endif

FindFirstFile的参数lpFindFile指向一个字符串,代表要寻找的文件名,如果文件名中不锯含路径,将在当前目录中查找文件.在文件名中可以包含'*'或'?'通配符
FindFirstFile函数和FindNextFile函数中的lpFindFileData参数则指向一个缓冲区,函数会在缓冲区中返回一个WIN_FIND_DATA结构,结构中包括了Windows查找过程中临时使用的数据和找到的文件名与属性等数据,该结构定义如下:

WIN32_FIND_DATA STRUCT
dwFileAttributes DWORD ? ;文件属性
ftCreationTime FILETIME <> ;文件的创建日期
ftLastAccessTime FILETIME <> ;文件的最后存取日期
ftlastWriteTime FILETIME <> ;文件的最后修改日期
nFileSizeHigh DWORD ? ;文件长度的高32位
nFileSizeLow DWORD ? ;文件长度的低32位
dwReserved0 DWORD ? ;内部使用
dwReserved1 DWORD ? ;内部使用
cFileName BYTE MAX_PATH dup(?) ;本次找到的文件名
cAlternate BYTE 14 dup(?) ;文件的8.3结构的短文件名
WIN32_FIND_DATA ENDS

dwFileAttributes字段可以是下面取值的组合,通过它可以检查找到的是一个文件还是一个子目录,以及属性
FILE_ATTRIBUTE_ARCHIVE:文件包含归档属性
FILE_ATTRIBUTE_COMPRESSED:文件和目录被压缩
FILE_ATTRIBUTE_DIRECTORY:找到的是一个目录
FILE_ATTRIBUTE_HIDDEN:文件包含隐含属性
FILE_ATTRIBUTE_NORMAL:文件没有其它属性
FILE_ATTRIBUTE_READONLY:文件包含只读属性
FILE_ATTRIBUTE_SYSTEM:文件包含系统属性
FILE_ATTRIBUTE_TEMPORARY:文件是一个临时文件
注意:cFileName字段中包括了找到的文件名,这个文件名中并不包含路径.

Windows 文件操作 — 创建和读写

1 打开和关闭文件
打开文件使用CreateFile 用法如下

invoke CreateFile,lpFileName,dwDesiredAccess,dwShareMode,lpSecurityAttributes,dwCreationDisposition,dwFlagsAndAttributes,hTemplateFile

各参数含义如下:
lpFileName:指向存放有文件名的缓冲区,文件名是以0结尾的字符串,字符最大长度为MAX_PATH(windows.inc中为260),可以打开多种对象,包括:控制台(Consoles),通信设备(Communications resources)-包括串口等,目录(Directories)和文件(Files),邮件槽(Mailslots),管道(Pipes)

dwDesiredAccess参数是存取方式,可以取的值有两个
GENERIC_READ 表示读取文件数据
GENERIC_WRITE 表示写数据
如果要读写数据,要同时指定这两个标志

dwShareMode参数是共享属性,表明文件被打开后是否允许其它进程再次打开文件, 可以取的值有四个
0:不允许文件再被打开
FILE_SHARE_DELETE:允许其它进程同时对文件进行删除
FILE_SHARE_READ:允许其它进程以读方式打开文件
FILE_SHARE_WRITE:允许其它进程同时以写方式打开文件

lpSecurityAttributes参数为安全属性,指定文件句柄是否可以被子进程继承,为NULL表明无法被继承,否则要将参数指向一个SECURITY_ATTRIBUTES结构,该结构定义如下

SECURITY_ATTRIBUTES STRUCT
nLength DWORD ? ;本结构的长度
lpSectrityDescriptor DWORD ?
bInheritHandle DWORD ? ;是否允许继承
SECURITY_ATTRIBUTES ENDS

将nLength设置为结构的长度,将bInheritHandle设置为TRUE就可以使句柄能够被子进程继承

dwCreationDisposition参数用来设置文件已经存在或不存在时系统采取的动作,在这里可以指定函数要执行的功能是创建还是打开.共有5个值:
CREATE_NEW:创建新文件,如果文件以存在函数会返回失败
CREATE_ALWAYS:创建新文件,如果文件以存在则清除原文件
OPEN_EXISTING:打开存在的文件,当文件不存在时函数返回失败
OPEN_ALWAYS:如果文件以存在,则打开,不存在则创建新文件
TRUNCATE_EXISTING:打开文件并将文件截断为零,当文件不存在时,返回失败

dwFlagsAndAttributes参数用来指定新建文件的属性,可以有10个值
FILE_ATTRIBUTE_NORMAL:普通文件,设置这个属性时其他属性都不会生效
FILE_ATTRIBUTE_ARCHIVE:设置归档属性
FILE_ATTRIBUTE_HIDDEN:设置隐藏属性
FILE_ATTRIBUTE_READONLY:设置只读属性
FILE_ATTRIBUTE_SYSTEM:设置系统属性
FILE_ATTRIBUTE_TEMPORARY:临时文件,系统会尽量把文件内容保持在内存中,以加快存取速度,程序在不使用它时会尽快删除它
此外还可以指定对文件操作的方式
FILE_FLAG_WRITE_THROUGH:使用WriteThrough模式,系统不会对文件使用缓存.
FILE_FLAG_OVERLAPPED:使用异步文件操作模式
FILE_FLAG_DELETE_ON_CLOSE:文件被关闭后立即被系统自动删除
FILE_FLAG_RANDOM_ACCESS:对文件进行随机读写操作

hTemplateFile:指定了一个文件模板的句柄,该文件模板的所有属性都会被复制到当前创新的文件中.win95不支持本参数,建议在参数中使用NULL.当打开或创建文件成功的时候函数返回一个文件句柄,失败返回INVALID_HANDLE_VALUE,这个值是-1而不是NULL

关闭文件用

invoke CloseHandle,hFile

2移动文件指针
调整文件指针使用SetFilePointer函数

invoke SetFilePointer,hFile,lDistanceToMove,lpDistanceToMoveHigh,dwMoveMethod

hFile:是CreateFile返回的文件句柄
lDistanceToMove:指定要移动的距离.
ldistanceToMoveHigh:是一个指针指向一个32位变量存放移动距离的高32位,他与lDistanceToMove组成一个64位地址,但在X86平台上的windows版本中,文件长度不会超过4G,所以一般设置为NULL
dwMoveMethod指定了移动模式,有3个值
FILE_GEGIN:总是从文件头部开始移动
FILE_CURRENT:从当前的文件指针处开始移动
FILE_END:从文件尾开始移动
当lDistanceToMoveHigh=NULL时,如果函数执行失败返回值是-1,否则返回新的文件指针

可以使用以下代码获得当前指针的位置

invoke SetFilePointer,hFile,0,NULL,FILE_CURRENT

SetEndOfFile设置文件长度

invoke SetEndOfFile,hFile

3读写文件
读写文件可以使用ReadFile/WriteFile,这两个函数读写方式可以是同步或异步
也可以用ReadFileEx/WriteFileEx,这两个函数只用于异步读写

ReadFile用法

invoke ReadFile,hFile,lpBuffer,nNumberOfBytesToRead,lpNumberOfBytesRead,lpOverlapped

hFile是文件句柄
lpBuffer指向一个缓冲区,函数会将读出的数据传送到这里
nNumberOfBytesToRead指定需要读入的字节数
lpNumberOfBytesRead指向一个dword变量,函数将在这里返回实际读入的字节数
lpOverlapped参数指向一个OVERLAPPED结构,供函数在异步读取文件时使用,同步读写中为NULL
读取文件失败,则返回0,成功则函数返回非0值
例:

invoke ReadFile,@hFile,addr @szReadBuffer,sizeof @szReadBuffer,addr @dwBytesRead,0

读出的字节数保存在@dwBytesRead中.

WriteFile用法

invoke WriteFile,hFile,lpBuffer,nNumberOfBytesToWrite,lpNumberOfBytesWriten,lpOverlapped

hFile:文件句柄
lpBuffer:指向一个缓冲区,当中包含有要写入的文件数据
nNumberOfBytesToWrite:指定要写入的字节数
lpNumberOfBytesWriten:函数在这里返回成功写入的字节数
lpOverlapped:异步结构,同步时为NULL
写入文件时可能会由于多种原因使数据丢失
可以使用FlushFileBuffers函数来清空数据缓冲区

invoke FlushFileBuffers,hFile

总之如果这个函数执行成功的话,就能够保证所有的数据以经被传送.如果成执行成功返回值是非0值,失败返回0

4文件的共享
加锁可以防止其他进程对该区域进行读取或写入操作,加锁与解锁使用LockFile与UnlockFile也可以使用LockFileEx与UnlockFileEx,这两个函数使用异步方式执行.

invoke LockFile,hFile,dwFileOffsetLow,dwFileOffsetHigh,nNumberOfBytesToLockLow,nNumberOfBytesToLockHigh
invoke UnlockFile,hFile,dwFileOffsetLow,dwFileOffsetHigh,nNumberOfBytesToLockLow,nNumberOfBytesToLockHigh

dwFileOffsetLow和dwFileOffsetHigh参数组合起来指定了加锁区域的开始位置
dwNumberOfBytesToLockLow和dwNumberOfBytesToLockHigh组合指定加锁区域的大小,windows中,可以只使用低32位
注意:不能对一个区域重复加锁,两个不同的加锁区域也不能重叠,在对文件加锁与解锁操作的区域也必须一一对应,必须一次全部解锁,不能分次解锁.当程序读取一个可能被其它时程加锁的程序时,如果读取失败,必须调用GetLastError来获取失败原因,如果是因为锁定造成的,那可以等待一段时间后继续读取.

关于组播的特殊地址

224.0.0.0 - Base address
224.0.0.1 - 网段中所有支持多播的主机
224.0.0.2 - 网段中所有支持多播的路由器
224.0.0.4 - 网段中所有的DVMRP路由器
224.0.0.5 - 所有的OSPF路由器
224.0.0.6 - 所有的OSPF指派路由器
224.0.0.7 - 所有的ST路由器
224.0.0.8 - 所有的ST主机
224.0.0.9 - 所有RIPv2路由器
224.0.0.10 - 网段中所有支的路由器
224.0.0.11 - Mobile-Agents
224.0.0.12 - DHCP server / relay agent.
224.0.0.13 - 所有的PIM路由器
224.0.0.22 - 所有的IGMP路由器
224.0.0.251 - 所有的支持组播的DNS服务器