|
楼主 |
发表于 2008-5-12 03:57:40
|
显示全部楼层
第五章
THE STARCRAFT CAMPAIGN EDITOR AND THE MPQ API LIBRARY
星际争霸编辑器和MPQ API LIBRARY
Starcraft Campaign Editor 是什么呢?其实就是一个能让您自己作出星际争霸地图的程序。
并把地图以SCM格式保存,或者保存为SCX文件。
可是这些个SCM/SCXs文件 和Warcraft 2是一样的原始文件?
假如您用hex editor 看过这些文件,那么您会得到一个否定的答案。
实际上SCM/SCXs就是MPQ文件!!
那么你也许认为很简单,那你就错了,StarEdit使用了一套难以捉摸的MPQ编写套路。
不过在您仔细阅读下面的内容,您将会得到答案。
Using StarEdit - The MPQ API Library
使用编辑器- The MPQ API Library
注意:这章是针对WINDOWS平台的,适用于THE MPQ API LIBRARY 2.0或更高!
在这里我们并不能很快的编译,因为编辑器有的功能我们并不能直接使用。
不像STROM之类的shared libraries ,StarEdit拥有复杂的操作系统保护机智,而不只是对于文件的保护。就算您是一位很好的程序员,您一样无法直接修改它。对于这种高难度的熟练的对运行系统的改写,还没有人能完成过。 就在这个时候Andrey Lelikov (简称Lelik)横空出世。
Lelik是一位熟悉系统内部工作机制的俄罗斯程序员。他设计了一个能够使用 StarEdit MPQ 的方法。
他把自己写的详细功能放进了MPQ API Library 。
就像STROM,MPQ API Library(又名LMPQAPI),它包含了共享库(可惜的是,像STROM接口库,现在在MAC机上还没有)。LMPQAPI不仅包括了StarEdit的MPQ编写功能,而且提供接口读写STROM。
如果您想同时使用STROM和StarEdit,您不需要同时使用LMPQAPI和STROM接口库。
一个LMPQAPI足已。
好吧。我提醒您一件事,您想在使用LMPQAPI的时候区分是用STROM还是StarEdit么?
STROM功能有就像使用STROM接口库时一样有一个前缀'SFile',在使用StarEdit时,前缀是'Mpq'。
这是很重要的,因为这说明了STROM和StarEdit的功能不兼容。
这意味着您无法用SFileOpenArchive获得的MPQ HANDLE去在StarEdit('Mpq'前缀的函数)里调用,反之亦然。 如果您还是调用的话,调用会失败,程序会崩溃。记住这点。
¿Sé Habla Español?
让人讲西班牙语?
因为75%以上的星际争霸或暗黑的玩家是以英语为母语,所以大多数MPQ开发测试都基于这些游戏的英文版。对于使用英文版游戏的玩家,MPQ会运行良好。但事实上,98%的标准MPQ文件使用的是language-neutral (比如图象文件等等)。甚至有人用全非英语的MPQ玩游戏也没有问题。
不过,很明显这里是有问题的,只是还要等些时间才有人能发现吧。
做为上面两章的解释,MPQ格式具有强大的多国语言功能。
但是,您完全没必要做多语言的SCM/SCXs。
这就是说,您完全不必要让StarEdit支持多语言功能,就连暴雪的程序员都懒的做。
但是我们都有兴趣研究MPQ,除非没必要,其中的许多语言功能还是有用的。
在技术方面说,所有的StarEdit功能都只运行有语言代码为0或language-neutral代码的文件。
也就是说,MpqAddFileToArchive和MpqAddWAVToArchive只增加language- neutral files, MpqDeleteFile只删除language-neutral files, MpqRenameFile 只会重命名language-neutral files.
这种设计决定了,执行结果并不明显。在前一章也提到过,假如在打开有相同名称不同语言的文件时,STROM使用了SFileSetLocale做为语言过滤器,用来决定到底打开哪个文件。
假设在StarEdit使用一个MPQ文件代替patch_rt.mpq ,而且在那个MPQ文件里有英语/language-neutral解析度文件rez\\gluAll.tbl (这文件内有多个语言版本),但是不能有葡萄牙语版本(选定任意语言)。
当您运行这个游戏的葡萄牙语版时,程序会查询在您MPQ文件中的该语言版。结果就是失败,而且默认又为英语版本的,对不对?
好吧,不是这样的。STROM允许您同时打开几个MPQ文件,并且STROM会搜索已经加载的MPQ,然后自动加载最新的MPQ到文件里。但是在这个过程中,STROM在系统为language-neutral以前,会检查已经打开的所有特殊语言的MPQ。
这意味着,前面STROM从broodat.mpq 载入葡萄牙语版本,而不是您自己的language-neutral 版本。
很不幸,现在还没有解决的办法,希望新版本的LMPQAPI能被解决吧。
Initializing the MPQ API Library - MpqInitialize
初始化MPQ API Library函数- MpqInitialize
BOOL WINAPI MpqInitialize();
不像STROM,LMPQAPI在控制StarEdit时有巨大的复杂的任务要做。
因此,无法在启动LMPQAPI时做完一切。你必须告诉LMPQAPI什么时候运行。所幸,这很简单。
你要做的就是在您启动程序前调用MpqInitialize,LMPQAPI会自动做完剩下的。
请确定在调用LMPQAPI其他函数前,您调用了MpqInitialize。此外,即使您对STROM接口库什么都不做,也必须在任何STROM函数调用前被调用。
一次调用会同时初始化STROM和STAREIDT。
1.Starcraft/Brood War 1.07 必须已经安装,Storm.dll和StarEdit.exe必须在程序目录中
2.StarEdit不能和LMPQAPI一起运行.
为了调用MpqInitialize初始化上面的两个要求必须满足。尽管还有其他原因,上面两个却是最常见的。
不管什么原因,MpqInitialize调用失败后,都会返回FLASH,您可以检索GetLastError设置一个错误值。
如果LMPQAPI无法在游戏目录或在您程序的目录里无法找到StarEdit.exe ,那么GetLastError会返回MPQ_ERROR_NO_STAREDIT;
如果StarEdit.exe的版本不匹配,GetLastError会返回MPQ_ERROR_BAD_STAREDIT;
如果StarEdit已经运行GetLastError会返回MPQ_ERROR_STAREDIT_RUNNING;
如果是因为其他原因GetLastError通常会返回MPQ_ERROR_INIT_FAILED。
但是,无论为什么GetLastError调用失败,返回了什么,您要做的就是尽快的关闭程序。
不要调用任何LMPQAPI功能(STROM或者StarEdit的功能),当然也不要在调用MpqInitialize了。
Opening an MPQ for Editing - MpqOpenArchiveForUpdate
打开MPQ- MpqOpenArchiveForUpdate
HANDLE WINAPI MpqOpenArchiveForUpdate(LPCSTR lpFileName, DWORD dwCreationDisposition, DWORD dwHashTableSize);
| | Parameter | What it is | | | lpFileName | [in] A pointer to NULL-terminated string that holds the path of the MPQ to open. MpqOpenArchiveForUpdate will fail if this is NULL. | | | dwCreationDisposition | [in] Specifies what MpqOpenArchiveForUpdate should do with the archive if it does/doesn't exist. Must be one of the following values defined in lmpqapi.h: MOAU_CREATE_NEW | MpqOpenArchiveForUpdate will create a brand new archive. If lpFileName already exists, MpqOpenArchiveForUpdate will fail. | MOAU_CREATE_ALWAYS | MpqOpenArchiveForUpdate will create a new archive if lpFileName doesn't exist. If lpFileName does exist, it will be deleted and overwritten. | MOAU_OPEN_EXISTING | MpqOpenArchiveForUpdate will open the archive lpFileName. MpqOpenArchiveForUpdate will fail if lpFileName does not exist. | MOAU_OPEN_ALWAYS | If lpFileName exists, MpqOpenArchiveForUpdate will open it. If it doesn't, MpqOpenArchiveForUpdate will create a new archive. | MOAU_MAINTAIN_LISTFILE | This flag specifies that as MpqOpenArchiveForUpdate uses the archive lpFileName, it should update the internal listfile, if one exists. This is a flag, and must be ORed (with the | operator) with one of the other options for dwCreationDisposition |
| | | dwHashTableSize | [in] Whenever MpqOpenArchiveForUpdate creates a new archive (see the dwCreationDisposition for details on when this occurs), dwHashTableSize specifies how large the hash table for the new archive will be, with a minimum size of 16, and a maximum size of 262,144 (if dwHashTableSize is not within these values, MpqOpenArchiveForUpdate will change it). This parameter does not affect archives that already exist. |
与STROM一样,您在使用前必须先打开它.
MpqOpenArchiveForUpdate 打开(或创建)一个存档,这是为了您使用其他StarEdit功能的,并返回存档的HANDLE.
但是不像SFileOpenArchive,MpqOpenArchiveForUpdate需要您在时间上做出选择.
第一选择是dwcreationdisposition参数。它告诉mpqopenarchiveforupdate是否应该创建一个新的存档还是打开一个现有的,或两者之间。其他的决定性参数是dwhashtablesize 。 dwhashtablesize告诉mpqopenarchiveforupdate创建什么大小存档的哈希表(这也是该文件限制),在
mpqopenarchiveforupdate事件中必须创建要一个新的存档。
做为一个存档的哈希表大小差不多是1000,除非你知道存档一定会超过1000个文件。
但同时请记住,每个哈希表项和存档文件将新增16个字节,(见第2章的哈希表,或第5章关于mpq哈希表的更多信息) 。
在上面的进程中MpqOpenArchiveForUpdate可能调用失败.
MpqOpenArchiveForUpdate将返回INVALID_HANDLE_VALUE或者NULL.
我们根据调用GetLastError通常可以获取有用的信息,但不是绝对.
如果lpfilename参数为空, getlasterror将返回error_invalid_parameter 。
如果dwcreationdisposition返回moau_open_existing或者lpfilename不存在, getlasterror将返回error_file_not_found 。反过来说,如果dwcreationdisposition返回moau_create_new和档案lpfilename已经存在, getlasterror将返回error_already_exists 。
最后,如果mpq存档存在,但是是无效或损坏的, getlasterror将返回mpq_error_mpq_invalid 。
在一些罕见的情况下, getlasterror将返回其他一些错误代码。
Closing a Modified Archive - MpqCloseUpdatedArchive
关闭修改过的存档- MpqCloseUpdatedArchive
| BOOL WINAPI MpqCloseUpdatedArchive(HANDLE hMPQ, DWORD dwUnknown);
| | Parameter | What it is | | | hMPQ | [in] The HANDLE of the MPQ to close, which was acquired earlier with MpqOpenArchiveForUpdate. MpqCloseUpdatedArchive will fail (or worse) if this is NULL or a HANDLE not obtained with MpqOpenArchiveForUpdate. | | | dwUnknown | Unknown. Should always be NULL. |
|
这里和在STROM中一样,您在哪用SFileOpenArchive打开MPQ,那么就在修改它的地方用SFileCloseArchive 关闭.
那么MPQ存档打开时用MpqOpenArchiveForUpdate,关闭时用MpqCloseUpdatedArchive.
然而在这时候有一点区别.STROM不会修改实际MPQ,所以关闭MPQ HANDLE时没有什么特别需要做的.
但是StarEdit 确实修改了MPQ.而且MPQ的散列值和文件表是在没有调用MpqCloseUpdatedArchive关闭MPQ HANDLE前不能写在MPQ分区的.
这意味着要快速关闭StarEdit MPQ HANDLEs,要不然您有可能再次程序崩溃,而无法保存修改的MPQ.
Adding a File - MpqAddFileToArchive
添加文件函数- MpqAddFileToArchive
| BOOL WINAPI MpqAddFileToArchive(HANDLE hMPQ, LPCSTR lpSourceFileName, LPCSTR lpDestFileName, DWORD dwFlags); | | Parameter | What it is | | | hMPQ | [in] The HANDLE of the MPQ to add the file to, which was acquired earlier with MpqOpenArchiveForUpdate. MpqAddFileToArchive will fail if this is NULL or a HANDLE not obtained with MpqOpenArchiveForUpdate. | | | lpSourceFileName | [in] A pointer to a NULL-terminated string containing the path of the file on disk to add. MpqAddFileToArchive will crash if this is NULL. | | | lpDestFileName | [in] A pointer to a NULL-terminated string containing the name that the file will be given in the MPQ. MpqAddFileToArchive will crash if this is NULL. | | | dwFlags | [in] Flags specifying properties that MpqAddFileToArchive will apply to the file inside the MPQ. Must be a combination of the following flags specified in lmpqapi.h: MAFA_ENCRYPT | The file will be encrypted. | MAFA_COMPRESS | The file will be compressed. | MAFA_REPLACE_EXISTING | If the file lpDestFileName already exists in the MPQ, it will be replaced with the new file to be added |
|
|
往往大约 95%的时候会在使用 StarEdit MPQ功能时候添加文件. 对于这个任务, 您会用到的函数有MpqAddFileToArchive和它的姊妹功能MpqAddWAVToArchive (稍后讨论).
MpqAddFileToArchive在MPQ hMPQ分区添加文件lpSourceFileName 使用名称lpDestFileName, 并在这个过程中压缩 或/和 加密它.
由于一些设计上的疏漏,在您并没有完全明白前,MpqAddFileToArchive会是个大麻烦.
1.MpqAddFileToArchive并不检查lpSourceFileName和lpDestFileName是否为空.
就是说假如任一参数为空,您会再次看到程序崩溃.
2.覆盖MPQ中已有文件时MpqAddFileToArchive的运行机制.
当您调用MpqAddFileToArchive去添加的文件已经存在MPQ中(在这种情况下,你就不得不指定dwflags为mafa_replace_existing ),MpqAddFileToArchive会在不确定文件lpSourceFileName是否存在前就不分青红皂白地删除存在的文件lpDestFileName.
解决的办法很简单:确保lpsourcefilename和lpdestfilename是有效的(非空) ,以及确保lpsourcefilename存在之前,调用mpqaddfiletoarchive 。
现在您应该可以饶过所有的障碍,用mpqaddfiletoarchive成功添加文件了吧.
这时mpqaddfiletoarchive将允许返回TURE.
如果有错误,它将返回FALSE 。在这种情况下,少量的信息可调用getlasterror 。
如果该文件lpsourcefilename不存在, getlasterror将返回error_file_not_found (尽管它的有点晚) 如果哈希表是FULL(见第2章) , getlasterror将返回mpq_error_hash_table_full 。
如果该文件lpdestfilename已经存在 和在dwflags中未指定mafa_replace_existing , getlasterror将返回mpq_error_already_exists 。
但是,在很多情况下getlasterror将返回其他一些错误代码或没有代码。
Adding a File with WAV Compression - MpqAddWAVToArchive
添加WAV压缩文件函数- MpqAddWAVToArchive
| BOOL WINAPI MpqAddWAVToArchive(HANDLE hMPQ, LPCSTR lpSourceFileName, LPCSTR lpDestFileName, DWORD dwFlags, DWORD dwQuality); | | Parameter | What it is | | | hMPQ | [in] The HANDLE of the MPQ to add the file to, which was acquired earlier with MpqOpenArchiveForUpdate. MpqAddWAVToArchive will fail if this is NULL or a HANDLE not obtained with MpqOpenArchiveForUpdate. | | | lpSourceFileName | [in] A pointer to a NULL-terminated string containing the path of the file on disk to add. MpqAddWAVToArchive will crash if this is NULL. | | | lpDestFileName | [in] A pointer to a NULL-terminated string containing the name that the file will be given in the MPQ. MpqAddWAVToArchive will crash if this is NULL. | | | dwFlags | [in] Flags specifying properties that MpqAddWAVToArchive will apply to the file inside the MPQ. Must be a combination of the following flags specified in lmpqapi.h: MAFA_ENCRYPT | The file will be encrypted. | MAFA_REPLACE_EXISTING | If the file lpDestFileName already exists in the MPQ, it will be replaced with the new file to be added |
| | | dwQuality | [in] Specifies the quality the WAV file will be compressed to. Must be one of the following values defined in lmpqapi.h: MAWA_QUALITY_HIGH | Best sound quality, least compression. WAV lpDestFileName in MPQ will occupy the most space after compression (but still less space than if you had added the file with MpqAddFileToArchive instead) | MAWA_QUALITY_MEDIUM | Medium sound quality, medium compression. Balance between quality and compression. | MAWA_QUALITY_LOW | Highest compression, worst sound quality. WAV lpDestFileName in MPQ will occupy the least space after compression. |
|
|
毫无疑问,最流行的新功能的lmpqapi 2.0版(就是我做的) ,便有功能 mpqaddwavtoarchive 。
虽然mpqaddfiletoarchive能压缩约80 %的文件(非wav文件) ,它对WAV文件的压缩只有平均约5 % 。这是由于wav数据性质和它的不可压缩性。
在这里,对于wav压缩的压缩是必要的,而 mpqaddwavtoarchive就实现了这个功能。
尽管工作原理不同,MpqAddWAVToArchive的界面与 MpqAddFileToArchive却是几乎相同的。
唯一的区别就是多了一个新函数dwQuality。
参数设置后WAV将会被压缩。
不过不像mpqaddfiletoarchive的标准压缩, mpqaddwavtoarchive的wav压缩,实际上降低了wav的质量 。质量降低多少依赖于dwquality 。
如果您有一个音乐WAV而又想保证质量,那您就使用mawa_quality_high ,因为它最好的保留wav的质量;而同一个声音wav , mawa_quality_low通常是不行的,因为声调比较容易压缩失真; mawa_quality_medium往往是最有效的。
Deleting a File - MpqDeleteFile
删除文件函数 - MpqDeleteFile
| BOOL WINAPI MpqDeleteFile(HANDLE hMPQ, LPCSTR lpFileName);
| | Parameter | What it is | | | hMPQ | [in] The HANDLE of the MPQ to close, which was acquired earlier with MpqOpenArchiveForUpdate. MpqDelete will fail (or worse) if this is NULL or a HANDLE not obtained with MpqOpenArchiveForUpdate. | | | lpFileName | [in] A pointer to a NULL-terminated name of the file in the MPQ to delete. MpqDeleteFile will crash if this is NULL. |
|
少数情况下,您可能需要删除MPQ中的某个文件,那么您就需要用到MpqDeleteFile。
MpqDeleteFile能从已经打开的存档hMPQ中删除文件lpFileName。
不过这不是看上去那么简单的。
mpqdeletefile为lpfilename删除哈希和文件表项 ,使其无法进入。
但是除非文件在MPQ的physical end ,否则MpqDeleteFile无法清除内存。
这就是说,通常情况下MPQ文件是不会减小大小的。
不过空间可以添加新文件循环再利用。稍后为您介绍MpqAddFileToArchive 和MpqAddWAVToArchive.
就像STROM和STAREDIT几乎所有的功能一样,调用MpqDeleteFile成功就返回TURE,失败就返回FALSE。
失败的话,您可以调用GetLastError去获得一些关于失败原因的信息(假如有的话)。
在这种情况下GetLastError是惊人的有效。
因为几乎只有一种会造成MpqDeleteFile失败的原因(除了hMPQ无效):
该文件lpFileName不存在于MPQ,GetLastError将返回MPQ_ERROR_FILE_NOT_FOUND。
Renaming a File - MpqRenameFile
重命名文件函数- MpqRenameFile
BOOL WINAPI MpqRenameFile(HANDLE hMPQ, LPCSTR lpOldFileName, LPCSTR lpNewFileName); | | Parameter | What it is | | | hMPQ | [in] The HANDLE of the MPQ that holds the file to be renamed, and was acquired earlier with MpqOpenArchiveForUpdate. MpqRenameFile will fail if this is NULL or a HANDLE not obtained with MpqOpenArchiveForUpdate. | | | lpOldFileName | [in] A pointer to a NULL-terminated string containing the name of the file in the MPQ to be renamed. MpqRenameFile will fail if this is NULL. | | | lpNewFileName | [in] A pointer to a NULL-terminated string containing the name that the file lpOldFileName will be changed to. MpqRenameFile will fail if this is NULL |
在我慢慢研究MPQ后发现StarEdit缺少一对非常有用的功能。
而且那个时候我对与STROM和StarEdit的运做有了相当的了解,所以我决定写个自己的功能。
MpqRenameFile 非常的简单;它重新把hMPQ中的文件名 由lpOldFileName变为lpNewFileName.
mpqrenamefile返回给您的依旧是简单的信息。
mpqrenamefile返回true就成功,FLASH失败,并让您调用getlasterror获得失败的原因 。
如果hMPQ HANDLE 是NULL或无效,lpoldfilename或lpnewfilename是Null , getlasterror将返回error_invalid_parameter 。
如果该文件lpoldfilename不存在于MPQ hMPQ中, getlasterror将返回mpq_error_file_not_found 。
如果该文件lpnewfilename已经存在mpq中 , getlasterror将返回mpq_error_already_exists 。
Compacting an MPQ - MpqCompactArchive
压缩MPQ函数- MpqCompactArchive
| BOOL WINAPI MpqCompactArchive(HANDLE hMPQ, BOOL bFailOnBadFile); | | Parameter | What it is | | | hMPQ | [in] The HANDLE of the MPQ to compact, which was acquired earlier with MpqOpenArchiveForUpdate. MpqCompactArchive will fail if this is NULL or a HANDLE not obtained with MpqOpenArchiveForUpdate. | | | bFailOnBadFile | [in] Explained below. Should usually be FALSE |
|
记得我刚才说过调用mpqdeletefile实际上并不删除文件;它只是使它们无法使用。那么, mpqaddfiletoarchive和mpqaddwavtoarchive也是一样。
当您添加一个已经存在的文件或添加比旧文件大的新文件,新的文件将附加,和原来被占用的空间不会被释放。正因为如此,每当您建立一个大的复杂的包含许多覆盖/删除的档案的mpq,将会有很大的体积,并且没有办法从零重建MPQ。
解决这个问题的方法是调用mpqcompactarchive :这是我设计的第三个,也是最后一个,最困难的mpq功能。 mpqcompactarchive的功能是把数据压缩到一个缓冲文件,然后再传回。这就是说在压缩的时候,在磁盘上的缓冲文件必须有足够的可用空间(这取决于MPQ的大小)。
虽然mpqcompactarchive可以让几乎所有的文件变得紧凑,但是还是有不能成功的类型:有mafa_encrypt和mafa_modcryptkey属性,但缺乏mafa_compress和mafa_compress2属性的文件(如需详细资讯,请参阅第5章) 。当mpqcompactarchve调用这种文件,getlasterror会返回错误代码mpq_error_compact_error ,然后删除违规档案,并继续压缩过程。
mpqcompactarchive返回TURE就成功,FLASH就失败。您可以调用getlasterror获得错误信息 。
如果hmpq是Null或无效的staredit HANDLE, getlasterror将返回error_invalid_parameter 。
如果没有足够的可用记忆体为mpqcompactarchive拨出2.5 MB的读取缓冲区, getlasterror将返回error_outofmemory 。
如果没有足够的可用磁盘空间mpqcompactarchive分配缓冲文件, GetLastError返回error_disk_full 。在某些特殊的情况下, getlasterror可能会返回其他一些奇怪的错误代码。
Getting Information About a File - SFileGetFileInfo
获取文件有关信息函数 - SFileGetFileInfo
DWORD WINAPI SFileGetFileInfo(HANDLE hMPQorFile, DWORD dwInfoType);
| | Parameter | What it is | | | hMPQorFile | [in] The HANDLE of the either the MPQ or file inside an MPQ to obtain info about, which was acquired earlier with either SFileOpenArchive or SFileOpenFileEx. SFileGetFileInfo will fail (or worse) if this is NULL or a HANDLE not obtained with SFileOpenArchive or SFileOpenFileEx. | | | dwInfoType | [in] The type of info to obtain about the file or MPQ. Must be one of the following values defined in lmpqapi.h: SFILE_INFO_HASH_TABLE_SIZE | SFileGetFileInfo will return the hash table size of hMPQorFile (see chapters 2 and 5 for more info). hMPQorFile must be a HANDLE of an MPQ. | SFILE_INFO_NUM_FILES | SFileGetFileInfo will return the number of files inside hMPQorFile. hMPQorFile must be a HANDLE of an MPQ. | SFILE_INFO_SIZE | SFileGetFileInfo will return the size of the MPQ hMPQorFile or the uncompressed size of the file hMPQorFile. This is functionally equivalent to the SFileGetFileSize function. hMPQorFile can be either a HANDLE of an MPQ or a HANDLE of a file inside. | SFILE_INFO_COMPRESSED_SIZE | SFileGetFileInfo will return the compressed size (or uncompressed size if the file isn't compressed) of the file hMPQorFile in an MPQ. hMPQorFile must be a HANDLE of a file inside an MPQ. | SFILE_INFO_FLAGS | SFileGetFileInfo will return the flags (see chapter 5 for the meaning of specific flags) of the file hMPQorFile in an MPQ. hMPQorFile must be a HANDLE of a file inside an MPQ. | SFILE_INFO_POSITION | SFileGetFileInfo will return the absolute position of the file pointer for the file hMPQorFile in an MPQ. hMPQorFile must be a HANDLE of a file inside an MPQ. |
|
SFileGetFileInfo 是 LMPQAPI中最古怪的功能函数.
不仅是唯一可以通过LMPQAPI而不能通过STROM接口库的STROM功能。
它唯一的函数就是能够接受MPQ或者文件HANDLE,但在大多数情况下它根本不存在于STROM里。
为了补救这个,我自己写了了这个SFileGetFileInfo。
sfilegetfileinfo是专门设计来提供有用的mpq和其内档案的信息;包括mpq中压缩文件的大小,文件指针的位置。它使用简单,但相当有效。它使用已经打开了的mpq或文件的HANDLE,以获取有关hmpqorfile的信息 ,以及在dwinfotype中需要的信息类型代码。
如果sfilegetfileinfo成功,返回值就是有关文件或MPQ的资料 。
但是,如果失败的话,它会返回0xFFFFFFFF,并设置一个错误代码,您可以调用getlasterror查看 。
如果因为hmpqorfile HANDLE是无效的, getlasterror将返回error_invalid_parameter 。
如果因为dwinfotype是一个无效的信息代码,getlasterror将返回error_unknown_property 。 sfilegetfileinfo只在一种情况下会调用失败(除了严重的内部lmpqapi错误)。
因为一个mpq HANDLE和dwinfotype指定的信息只能得到一个文件HANDLE,或反之亦然,在这种情况下, getlasterror将返回error_unknown_property。 |
|