コード例 #1
0
ファイル: MpkManip.cpp プロジェクト: lorichen/xgame
	bool MpkManip::removeDir(const char* dir)
	{
		bool bOk = true;

		std::string strDir = dir;
		if(!strDir.empty())
			strDir = strDir + "\\*"; 
		else
			strDir = "*";

		SFILE_FIND_DATA fileFindData;
		HANDLE hFind = SFileFindFirstFile(m_hMpk,strDir.c_str(),&fileFindData,0);
		if(hFind)
		{
			do
			{
				if(!removeFile(fileFindData.cFileName))
				{
					bOk = false;
				}
			}
			while(SFileFindNextFile(hFind,&fileFindData));
			SFileFindClose(hFind);
		}

		return bOk;
	}
コード例 #2
0
ファイル: vmapexport.cpp プロジェクト: samaelsacred/4.3.4
bool ExtractWmo()
{
    bool success = false;

    //const char* ParsArchiveNames[] = {"patch-2.MPQ", "patch.MPQ", "common.MPQ", "expansion.MPQ"};

    SFILE_FIND_DATA data;
    HANDLE find = SFileFindFirstFile(WorldMpq, "*.wmo", &data, NULL);
    if (find != NULL)
    {
        do
        {
            std::string str = data.cFileName;
            //printf("Extracting wmo %s\n", str.c_str());
            success |= ExtractSingleWmo(str);
        }
        while (SFileFindNextFile(find, &data));
    }
    SFileFindClose(find);

    if (success)
        printf("\nExtract wmo complete (No (fatal) errors)\n");

    return success;
}
コード例 #3
0
ファイル: MpkManip.cpp プロジェクト: lorichen/xgame
	bool MpkManip::extractDir(const char* source,const char* target,bool replaceExist,IMpkManipCallback *pCallback,void *p)
	{
		bool bOk = true;

		std::string strSource = source;
		if(!strSource.empty())
			strSource = strSource + "\\*"; 
		else
			strSource = "*";

		SFILE_FIND_DATA fileFindData;
		HANDLE hFind = SFileFindFirstFile(m_hMpk,strSource.c_str(),&fileFindData,0);
		if(hFind)
		{
			do
			{
				std::string targetFilename = std::string(target) + "\\" + fileFindData.cFileName;
				if(pCallback)
				{
					pCallback->onProcessFile(fileFindData.cFileName,p);
				}

				if(!extractFile(fileFindData.cFileName,targetFilename.c_str(),replaceExist))
				{
					bOk = false;
				}
			}
			while(SFileFindNextFile(hFind,&fileFindData));
			SFileFindClose(hFind);
		}

		return bOk;
	}
コード例 #4
0
ファイル: MpkManip.cpp プロジェクト: lorichen/xgame
	const char* MpkManip::findNextFile()
	{
		if(m_hFind)
		{
			if(SFileFindNextFile(m_hFind,&m_FileFindData))
			{
				return m_FileFindData.cFileName;
			}
		}

		return 0;
	}
コード例 #5
0
ファイル: MpkManip.cpp プロジェクト: lorichen/xgame
	bool MpkManip::cleanupFragment(const char* mpkFilename)
	{
		bool bOk = false;
		HANDLE hMpk = 0;
		char tempFilename[MAX_PATH];
		if(SFileCreateArchiveEx(mpkFilename,OPEN_EXISTING,8000,&hMpk))
		{
			uint nTotal = SFileGetFileInfo(hMpk,SFILE_INFO_NUM_FILES);
			uint nFiles = 0;
			char tempPath[MAX_PATH];
			getTempPath(MAX_PATH, tempPath);
			getTempFileName(tempPath,tempFilename);

			HANDLE hTargetMpk = 0;
			if(SFileCreateArchiveEx(tempFilename,CREATE_ALWAYS,8000,&hTargetMpk))
			{
				SFILE_FIND_DATA fileFindData;
				HANDLE hFind = SFileFindFirstFile(hMpk,"*",&fileFindData,0);
				if(hFind)
				{
					do
					{
						const char* pFilename = fileFindData.cFileName;
						char tempFilename[MAX_PATH];
						getTempFileName(tempPath,tempFilename);
						if(SFileExtractFile(hMpk,pFilename,tempFilename))
						{
							if(SFileAddFile(hTargetMpk,tempFilename,pFilename,MPK_FILE_REPLACEEXISTING | MPK_FILE_COMPRESS_PKWARE))
							{
								nFiles++;
							}
						}
					}
					while(SFileFindNextFile(hFind,&fileFindData));

					if(nTotal == nFiles)bOk = true;
				}
				SFileCloseArchive(hTargetMpk);
			}

			SFileCloseArchive(hMpk);
		}

		if(bOk && copyFile(tempFilename,mpkFilename,FALSE))
		{
			bOk = true;
		}

		return bOk;
	}
コード例 #6
0
ファイル: System.cpp プロジェクト: Agyla/ArkCORE4
void ExtractDBCFiles(int l, bool basicLocale)
{
    printf("Extracting dbc files...\n");

    SFILE_FIND_DATA foundFile;
    memset(&foundFile, 0, sizeof(foundFile));
    HANDLE listFile = SFileFindFirstFile(LocaleMpq, "DBFilesClient\\*dbc", &foundFile, NULL);
    HANDLE dbcFile = NULL;
    uint32 count = 0;
    if (listFile)
    {
        std::string outputPath = output_path;
        outputPath += "/dbc/";

        CreateDir(outputPath);
        if (!basicLocale)
        {
            outputPath += Locales[l];
            outputPath += "/";
            CreateDir(outputPath);
        }

        std::string filename;

        do
        {
            if (!SFileOpenFileEx(LocaleMpq, foundFile.cFileName, SFILE_OPEN_PATCHED_FILE, &dbcFile))
            {
                printf("Unable to open file %s in the archive\n", foundFile.cFileName);
                continue;
            }

            filename = foundFile.cFileName;
            filename = outputPath + filename.substr(filename.rfind('\\') + 1);

            if (FileExists(filename.c_str()))
                continue;

            if (ExtractFile(dbcFile, filename.c_str()))
                ++count;

            SFileCloseFile(dbcFile);
        } while (SFileFindNextFile(listFile, &foundFile));

        SFileFindClose(listFile);
    }

    printf("Extracted %u DBC files\n\n", count);
}
コード例 #7
0
ファイル: System.cpp プロジェクト: Erotix8210/StrawberryCore
void AppendDBCFileListTo(HANDLE mpqHandle, std::set<std::string>& filelist)
{
    SFILE_FIND_DATA findFileData;

    HANDLE searchHandle = SFileFindFirstFile(mpqHandle, "*.dbc", &findFileData, NULL);
    if (!searchHandle)
        return;

    filelist.insert(findFileData.cFileName);

    while (SFileFindNextFile(searchHandle, &findFileData))
        filelist.insert(findFileData.cFileName);

    SFileFindClose(searchHandle);
}
コード例 #8
0
void MainWindow::listFilesDetails(QString extension, QStringList & list)
{
    extension = "*." + extension;

    SFILE_FIND_DATA findFileData;
    HANDLE findHandle = SFileFindFirstFile(mDiabdat, extension.toStdString().c_str(), &findFileData, NULL);
    
    list.append(QString(findFileData.cFileName));

    while (SFileFindNextFile(findHandle, &findFileData))
    {
        list.append(QString(findFileData.cFileName));
    }

    SFileFindClose(findHandle);
}
コード例 #9
0
ファイル: MpkManip.cpp プロジェクト: lorichen/xgame
	void MpkManip::dumpListFile()
	{
		SFILE_FIND_DATA fileFindData;
		HANDLE hFind = SFileFindFirstFile(m_hMpk,"*",&fileFindData,0);
		if(hFind)
		{
			do
			{
#ifdef _WIN32
				OutputDebugString(fileFindData.cFileName);
				OutputDebugString("\n");
#endif
			}
			while(SFileFindNextFile(hFind,&fileFindData));
			SFileFindClose(hFind);
		}
	}
コード例 #10
0
ファイル: faio.cpp プロジェクト: gnaghi/freeablo
    std::vector<std::string> listMpqFiles(const std::string& pattern)
    {
        SFILE_FIND_DATA findFileData;
        HANDLE findHandle = SFileFindFirstFile(diabdat, pattern.c_str(), &findFileData, NULL);

        std::vector<std::string> results;

        results.push_back(findFileData.cFileName);

        while (SFileFindNextFile(findHandle, &findFileData))
        {
            results.push_back(findFileData.cFileName);
        }

        SFileFindClose(findHandle);

        return results;
    }
コード例 #11
0
	void CMpqArchive::Load()
	{
		int nLen = strlen(m_szName.c_str()) + 1;  
		int nwLen = MultiByteToWideChar(CP_ACP, 0, m_szName.c_str(), nLen, NULL, 0);  
		TCHAR lpszFile[MAX_PATH];  
		MultiByteToWideChar(CP_ACP, 0, m_szName.c_str(), nLen, lpszFile, nwLen);  
		SFileOpenArchive(lpszFile, 0, MPQ_OPEN_FORCE_MPQ_V1 | MPQ_OPEN_READ_ONLY, &m_hMpq);
		
		m_szDir = CStringUtil::Combine(m_szName, "", false);

		SFILE_FIND_DATA data; bool bFind = true;
		HANDLE hFindFile = SFileFindFirstFile(m_hMpq, "*.*", &data, NULL);
		while (hFindFile != NULL && bFind)
		{
			CFileInfo info;
			info.m_szName = data.cFileName;
			info.m_nSize = data.dwFileSize;
			info.m_nCompSize = data.dwCompSize;
			m_vecFile.push_back(info);

			bFind = SFileFindNextFile(hFindFile, &data);
		}
		SFileFindClose(hFindFile);
	}
コード例 #12
0
ファイル: vmapexport.cpp プロジェクト: SADraco/mangos-cata
void LoadCommonMPQFiles(uint32 build)
{
    TCHAR filename[512];
    _stprintf(filename, _T("%sworld.MPQ"), input_path);
    if (!SFileOpenArchive(filename, 0, MPQ_OPEN_READ_ONLY, &WorldMpq))
    {
        if (GetLastError() != ERROR_FILE_NOT_FOUND)
            _tprintf(_T("Cannot open archive %s\n"), filename);
        return;
    }

    int count = sizeof(CONF_mpq_list) / sizeof(char*);
    for (int i = 1; i < count; ++i)
    {
        if (build < 15211 && !strcmp("world2.MPQ", CONF_mpq_list[i]))   // 4.3.2 and higher MPQ
            continue;

        _stprintf(filename, _T("%s%s"), input_path, CONF_mpq_list[i]);
        if (!SFileOpenPatchArchive(WorldMpq, filename, "", 0))
        {
            if (GetLastError() != ERROR_FILE_NOT_FOUND)
                _tprintf(_T("Cannot open archive %s\n"), filename);
            else
                _tprintf(_T("Not found %s\n"), filename);
        }
        else
        {
            _tprintf(_T("Loaded %s\n"), filename);

            bool found = false;
            int count = 0;
            SFILE_FIND_DATA data;
            HANDLE find = SFileFindFirstFile(WorldMpq, "*.*", &data, NULL);
            if (find != NULL)
            {
                do
                {
                    ++count;
                    if (data.dwFileFlags & MPQ_FILE_PATCH_FILE)
                    {
                        found = true;
                        break;
                    }
                }
                while (SFileFindNextFile(find, &data));
            }
            SFileFindClose(find);
            printf("Scanned %d files, found patch = %d\n", count, found);
        }
    }

    char const* prefix = NULL;
    for (int i = 0; Builds[i] && Builds[i] <= CONF_TargetBuild; ++i)
    {
        memset(filename, 0, sizeof(filename));
        if (Builds[i] > LAST_DBC_IN_DATA_BUILD)
        {
            prefix = "";
            _stprintf(filename, _T("%swow-update-base-%u.MPQ"), input_path, Builds[i]);
        }
        else
        {
            prefix = "base";
            _stprintf(filename, _T("%swow-update-%u.MPQ"), input_path, Builds[i]);
        }

        if (!SFileOpenPatchArchive(WorldMpq, filename, prefix, 0))
        {
            if (GetLastError() != ERROR_FILE_NOT_FOUND)
                _tprintf(_T("Cannot open patch archive %s\n"), filename);
            else
                _tprintf(_T("Not found %s\n"), filename);
            continue;
        }
        else
        {
            _tprintf(_T("Loaded %s\n"), filename);


            bool found = false;
            int count = 0;
            SFILE_FIND_DATA data;
            HANDLE find = SFileFindFirstFile(WorldMpq, "*.*", &data, NULL);
            if (find != NULL)
            {
                do
                {
                    ++count;
                    if (data.dwFileFlags & MPQ_FILE_PATCH_FILE)
                    {
                        found = true;
                        break;
                    }
                }
                while (SFileFindNextFile(find, &data));
            }
            SFileFindClose(find);
            printf("Scanned %d files, found patch = %d\n", count, found);
        }
    }

}
コード例 #13
0
ファイル: vmapexport.cpp プロジェクト: AwkwardDev/Summit
//----------------------------------------------------------------------------------------------------------------------------------------------------------------------
int ExtractWmo(const std::vector<std::string>& pArchiveNames)
{

    char* szListFile = ""; 
    char   szLocalFile[MAX_PATH] = "";
    HANDLE hMpq = ""; 
    BOOL bResult = FALSE;

    //const char* ParsArchiveNames[] = {"patch-2.MPQ", "patch.MPQ", "common.MPQ", "expansion.MPQ"};

    int nError = ERROR_SUCCESS;
    if(szListFile == NULL || *szListFile == 0)
        szListFile = NULL;
    //char tmp[1024];
    //for (size_t i=0; i<4; i++)
    for (size_t i=0; i<pArchiveNames.size(); i++)
    {

        //sprintf(tmp,"%s\\%s", input_path, ParsArchiveNames[i]);
        //if(!SFileOpenArchive(tmp, 0, 0, &hMpq))
        if(!SFileOpenArchive(pArchiveNames[i].c_str(), 0, 0, &hMpq))
            printf("NOT open!!! %s\n",pArchiveNames[i].c_str());

        // Copy files from archive
        if(nError == ERROR_SUCCESS)
        {	
            SFILE_FIND_DATA wf;
            HANDLE hFind = SFileFindFirstFile(hMpq,"*.wmo*", &wf, szListFile);
            bResult = TRUE;

            while(hFind != NULL && bResult == TRUE)
            {
                ShowProcessedFile(wf.cFileName);
                SFileSetLocale(wf.lcLocale);
                sprintf(szLocalFile, "%s\\%s", szWorkDirWmo, GetPlainName(wf.cFileName));
                fixnamen(szLocalFile,strlen(szLocalFile));
                FILE * n;
                if ((n = fopen(szLocalFile, "rb"))== NULL)
                {
                    int p = 0;
                    //Select root wmo files
                    const char * rchr = strrchr(GetPlainName(wf.cFileName),0x5f);
                    if(rchr != NULL)
                    {
                        char cpy[4];
                        strncpy((char*)cpy,rchr,4);
                        for (int i=0;i<4;i++)
                        {
                            int m = cpy[i];
                            if(isdigit(m))
                                p++;	
                        }
                    }
                    if(p != 3)
                    {
                        //printf("RootWmo!\n");
                        string s = wf.cFileName;
                        WMORoot * froot = new WMORoot(s);
                        if(!froot->open())
                        {
                            printf("Not open RootWmo!!!\n");
                            bResult = SFileFindNextFile(hFind, &wf);
                            continue;
                        }
                         FILE *output=fopen(szLocalFile,"wb");
                        froot->ConvertToVMAPRootWmo(output);
                        int Wmo_nVertices = 0;
                        if(froot->nGroups !=0)
                        {
                            for (int i=0; i<froot->nGroups; i++)
                            {
                                char temp[512];
                                strcpy(temp, wf.cFileName);
                                temp[strlen(wf.cFileName)-4] = 0;
                                char groupFileName[512];
                                sprintf(groupFileName,"%s_%03d.wmo",temp, i);
                                printf("%s\n",groupFileName);
                                //printf("GroupWmo!\n");
                                string s = groupFileName;
                                WMOGroup * fgroup = new WMOGroup(s);
                                if(!fgroup->open())
                                {
                                    printf("Not all open Group file for: %s\n",GetPlainName(wf.cFileName));
                                    bResult = SFileFindNextFile(hFind, &wf);
                                    break;
                                }
								Wmo_nVertices += fgroup->ConvertToVMAPGroupWmo(output, preciseVectorData);	
                            }
                        }
                        fseek(output, 8, SEEK_SET); // store the correct no of vertices
                        fwrite(&Wmo_nVertices,sizeof(int),1,output);
                        fclose(output);	
                    }
                } else {
                    fclose(n);
                }
                wf.dwFileFlags &= ~MPQ_FILE_HAS_EXTRA;
                wf.dwFileFlags &= ~MPQ_FILE_EXISTS;
                // Find the next file
                bResult = SFileFindNextFile(hFind, &wf);
            }
            // Delete the extracted file in the case of an error
            if(nError != ERROR_SUCCESS)
                DeleteFile(szLocalFile);
            // Close the search handle
            if(hFind != NULL)
                SFileFindClose(hFind);

        }
    }
    // Close both archives
    if(hMpq != NULL)
        //SFileCloseArchive(hMpq);
        if(nError == ERROR_SUCCESS)
            printf("\nExtract wmo complete (No errors)\n");

    return nError;

}
コード例 #14
0
static int CheckIfAllFilesKnown(TMPQArchive * ha, const char * szListFile, DWORD * pFileSeeds)
{
    TMPQHash * pHashTableCopy = NULL;   // Copy of the hash table
    TMPQHash * pHash;
    TMPQHash * pHashEnd = NULL;         // End of the hash table
    DWORD dwFileCount = 0;
    int nError = ERROR_SUCCESS;

    // First of all, create a copy of hash table
    if(nError == ERROR_SUCCESS)
    {
        if((pHashTableCopy = CopyHashTable(ha)) == NULL)
            nError = ERROR_NOT_ENOUGH_MEMORY;
        pHashEnd = pHashTableCopy + ha->pHeader->dwHashTableSize;

        // Notify the user
        if(CompactCB != NULL)
            CompactCB(lpUserData, CCB_CHECKING_FILES, 0, ha->pHeader->dwBlockTableSize);
    }

    // Now check all the files from the filelist
    if(nError == ERROR_SUCCESS)
    {
        SFILE_FIND_DATA wf;
        HANDLE hFind = SFileFindFirstFile((HANDLE)ha, "*", &wf, szListFile);
        BOOL bResult = TRUE;

        // Do while some files have been found
        while(hFind != NULL && bResult)
        {
            TMPQHash * pHash = GetHashEntry(ha, wf.cFileName);

            // If the hash table entry has been found, find it's position
            // in the hash table copy
            if(pHash != NULL)
            {
                pHash = pHashTableCopy + (pHash - ha->pHashTable);
                if(pHash->dwName1 != (DWORD)-1 && pHash->dwName2 != (DWORD)-1)
                {
                    TMPQBlock * pBlock = ha->pBlockTable + pHash->dwBlockIndex;
                    DWORD dwSeed = 0;

                    // Resolve the file seed. Use plain file name for it
                    if(pBlock->dwFlags & MPQ_FILE_ENCRYPTED)
                    {
                        char * szFileName = strrchr(wf.cFileName, '\\');

                        if(szFileName == NULL)
                            szFileName = wf.cFileName;
                        else
                            szFileName++;

                        dwSeed = DecryptFileSeed(szFileName);
                        if(pBlock->dwFlags & MPQ_FILE_FIXSEED)
                            dwSeed = (dwSeed + pBlock->dwFilePos) ^ pBlock->dwFSize;
                    }
                    pFileSeeds[pHash->dwBlockIndex] = dwSeed;

                    pHash->dwName1      = 0xFFFFFFFF;
                    pHash->dwName2      = 0xFFFFFFFF;
                    pHash->lcLocale     = 0xFFFF;
                    pHash->wPlatform    = 0xFFFF;
                    pHash->dwBlockIndex = 0xFFFFFFFF;
                }
            }
            // Notify the user
            if(CompactCB != NULL)
                CompactCB(lpUserData, CCB_CHECKING_FILES, ++dwFileCount, ha->pHeader->dwBlockTableSize);

            // Find the next file in the archive
            bResult = SFileFindNextFile(hFind, &wf);
        }

        if(hFind != NULL)
            SFileFindClose(hFind);
    }

    // When the filelist checking is complete, parse the hash table copy and find the
    if(nError == ERROR_SUCCESS)
    {
        // Notify the user about checking hash table
        dwFileCount = 0;
        if(CompactCB != NULL)
            CompactCB(lpUserData, CCB_CHECKING_HASH_TABLE, dwFileCount, ha->pHeader->dwBlockTableSize);

        for(pHash = pHashTableCopy; pHash < pHashEnd; pHash++)
        {
            // If there is an unresolved entry, try to detect its seed. If it fails,
            // we cannot complete the work
            if(pHash->dwName1 != (DWORD)-1 && pHash->dwName2 != (DWORD)-1)
            {
                HANDLE hFile  = NULL;
                DWORD dwFlags = 0;
                DWORD dwSeed  = 0;

                if(SFileOpenFileEx((HANDLE)ha, (char *)(DWORD_PTR)pHash->dwBlockIndex, SFILE_OPEN_BY_INDEX, &hFile))
                {
                    TMPQFile * hf = (TMPQFile *)hFile;
                    dwFlags = hf->pBlock->dwFlags;
                    dwSeed = hf->dwSeed1;
                    SFileCloseFile(hFile);
                }

                // If the file is encrypted, we have to check 
                // If we can apply the file decryption seed
                if(dwFlags & MPQ_FILE_ENCRYPTED && dwSeed == 0)
                {
                    nError = ERROR_CAN_NOT_COMPLETE;
                    break;
                }

                // Remember the seed
                pFileSeeds[pHash->dwBlockIndex] = dwSeed;

                // Notify the user
                if(CompactCB != NULL)
                    CompactCB(lpUserData, CCB_CHECKING_HASH_TABLE, ++dwFileCount, ha->pHeader->dwBlockTableSize);
            }
        }
    }

    // Delete the copy of hash table
    if(pHashTableCopy != NULL)
        FREEMEM(pHashTableCopy);
    return nError;
}
コード例 #15
0
static int CheckIfAllFilesKnown(TMPQArchive * ha, const char * szListFile, DWORD * pFileKeys)
{
    TMPQHash * pHashTableCopy = NULL;   // Copy of the hash table
    TMPQHash * pHash;
    TMPQHash * pHashEnd = NULL;         // End of the hash table
    DWORD dwFileCount = 0;
    int nError = ERROR_SUCCESS;

    // First of all, create a copy of hash table
    if(nError == ERROR_SUCCESS)
    {
        if((pHashTableCopy = CopyHashTable(ha)) == NULL)
            nError = ERROR_NOT_ENOUGH_MEMORY;
        pHashEnd = pHashTableCopy + ha->pHeader->dwHashTableSize;

        // Notify the user
        if(CompactCB != NULL)
            CompactCB(pvUserData, CCB_CHECKING_FILES, &CompactBytesProcessed, &CompactTotalBytes);
    }

    // Now check all the files from the listfile
    if(nError == ERROR_SUCCESS)
    {
        SFILE_FIND_DATA wf;
        HANDLE hFind = SFileFindFirstFile((HANDLE)ha, "*", &wf, szListFile);
        bool bResult = true;

        // Do while something has been found
        while(hFind != NULL && bResult)
        {
            TMPQHash * pHash = ha->pHashTable + wf.dwHashIndex;

            // Find the entry in the hash table copy
            pHash = pHashTableCopy + (pHash - ha->pHashTable);
            if(pHash->dwBlockIndex != HASH_ENTRY_FREE)
            {
                TMPQBlock * pBlock = ha->pBlockTable + pHash->dwBlockIndex;
                DWORD dwFileKey = 0;

                // Resolve the file key. Use plain file name for it
                if(pBlock->dwFlags & MPQ_FILE_ENCRYPTED)
                {
                    const char * szPlainName = GetPlainMpqFileName(wf.cFileName);

                    dwFileKey = DecryptFileKey(szPlainName);
                    if(pBlock->dwFlags & MPQ_FILE_FIX_KEY)
                        dwFileKey = (dwFileKey + pBlock->dwFilePos) ^ pBlock->dwFSize;
                }

                // Give the key to the caller
                pFileKeys[pHash->dwBlockIndex] = dwFileKey;

                pHash->dwName1      = 0xFFFFFFFF;
                pHash->dwName2      = 0xFFFFFFFF;
                pHash->lcLocale     = 0xFFFF;
                pHash->wPlatform    = 0xFFFF;
                pHash->dwBlockIndex = HASH_ENTRY_FREE;
            }

            // Find the next file in the archive
            bResult = SFileFindNextFile(hFind, &wf);
        }

        if(hFind != NULL)
            SFileFindClose(hFind);
    }

    // When the filelist checking is complete, parse the hash table copy and find the
    if(nError == ERROR_SUCCESS)
    {
        // Notify the user about checking hash table
        dwFileCount = 0;
        if(CompactCB != NULL)
            CompactCB(pvUserData, CCB_CHECKING_HASH_TABLE, &CompactBytesProcessed, &CompactTotalBytes);

        for(pHash = pHashTableCopy; pHash < pHashEnd; pHash++)
        {
            // If there is an unresolved entry, try to detect its key. If it fails,
            // we cannot complete the work
            if(pHash->dwBlockIndex < ha->pHeader->dwBlockTableSize)
            {
                HANDLE hFile  = NULL;
                DWORD dwFlags = 0;
                DWORD dwFileKey  = 0;

                if(SFileOpenFileEx((HANDLE)ha, (char *)(DWORD_PTR)pHash->dwBlockIndex, SFILE_OPEN_BY_INDEX, &hFile))
                {
                    TMPQFile * hf = (TMPQFile *)hFile;
                    dwFlags = hf->pBlock->dwFlags;
                    dwFileKey = hf->dwFileKey;
                    SFileCloseFile(hFile);
                }

                // If the file is encrypted, we have to check
                // If we can apply the file decryption key
                if((dwFlags & MPQ_FILE_ENCRYPTED) && dwFileKey == 0)
                {
                    nError = ERROR_CAN_NOT_COMPLETE;
                    break;
                }

                // Give the key to the caller
                pFileKeys[pHash->dwBlockIndex] = dwFileKey;
            }
        }
    }

    // Delete the copy of hash table
    if(pHashTableCopy != NULL)
        FREEMEM(pHashTableCopy);
    return nError;
}