Beispiel #1
0
WinHelpFileHeader::WinHelpFileHeader(QFile &file, qint64 off)
{
    PRINT_DBG("Reading WinHelp file header at %lld", off);
    seekFile(file, off);
    quint32 magicIn = readUnsignedDWord(file);
    if (magicIn != magic)
    {
        throw std::runtime_error("Not a WinHelp file header");
    }
    PRINT_DBG("        Magic: %d", magicIn);
    this->directoryStart = static_cast<qint64> (readUnsignedDWord(file));
    PRINT_DBG("        Directory start: %lld", this->directoryStart);
    this->firstFreeBlock = static_cast<qint64> (readUnsignedDWord(file));
    PRINT_DBG("        FirstFreeBlock: %lld", this->firstFreeBlock);
    this->entireFileSize = static_cast<qint64> (readUnsignedDWord(file));
    PRINT_DBG("        Entire file size: %lld", this->entireFileSize);
    PRINT_DBG("WinHelp file header loaded successfully");
}
Beispiel #2
0
quint32 readCompressedUnsignedDWord(QIODevice &device)
{
    qint64 pos = device.pos();
    quint8 lowByte = readUnsignedByte(device);
    if((lowByte & 1) != 0)
    {
        seekFile(device, pos);
        return readUnsignedDWord(device) / 2;
    }
    else
    {
        seekFile(device, pos);
        return static_cast<quint32>(readUnsignedWord(device)) / 2;
    }
}
BitmapCoreHeaderObject::BitmapCoreHeaderObject(QIODevice &device)
{
    this->headerSize = readUnsignedDWord(device);
    if(this->headerSize != 12)
    {
        throw std::runtime_error("Invalid bitmap core header size");
    }
    this->width = readUnsignedWord(device);
    this->height = readUnsignedWord(device);
    this->planes = readUnsignedWord(device);
    if(this->planes != 1)
    {
        throw std::runtime_error("Invalid bitmap planes count");
    }
    this->bitCount = readUnsignedWord(device);
}
Beispiel #4
0
qint32 readCompressedSignedDWord(QIODevice &device)
{
    qint64 pos = device.pos();
    quint8 lowByte = readUnsignedByte(device);
    if((lowByte & 1) != 0)
    {
        seekFile(device, pos);
        return static_cast<qint32>((static_cast<qint64>(readUnsignedDWord(
                        device)) - Q_INT64_C(0x80000000)) / Q_INT64_C(2));
    }
    else
    {
        seekFile(device, pos);
        return static_cast<qint32>((static_cast<qint64>(readUnsignedWord(device))
                - Q_INT64_C(0x8000)) / Q_INT64_C(2));
    }
}
Beispiel #5
0
MetafileRecord::MetafileRecord(QIODevice &device)
{
    this->recordSizeInWords = readUnsignedDWord(device);
    this->recordFunction = readUnsignedWord(device);
    bool validRecordType = false;
    switch(this->recordFunction & 0x00FF)
    {
    case (META_EOF & 0x00FF):
        validRecordType = true;
        break;
    case (META_REALIZEPALETTE & 0x00FF):
        validRecordType = true;
        break;
    case (META_SETPALENTRIES & 0x00FF):
        validRecordType = true;
        break;
    case (META_SETBKMODE & 0x00FF):
        validRecordType = true;
        break;
    case (META_SETMAPMODE & 0x00FF):
        validRecordType = true;
        break;
    case (META_SETROP2 & 0x00FF):
        validRecordType = true;
        break;
    case (META_SETRELABS & 0x00FF):
        validRecordType = true;
        break;
    case (META_SETPOLYFILLMODE & 0x00FF):
        validRecordType = true;
        break;
    case (META_SETSTRETCHBLTMODE & 0x00FF):
        validRecordType = true;
        break;
    case (META_SETTEXTCHAREXTRA & 0x00FF):
        validRecordType = true;
        break;
    case (META_RESTOREDC & 0x00FF):
        validRecordType = true;
        break;
    case (META_RESIZEPALETTE & 0x00FF):
        validRecordType = true;
        break;
    case (META_DIBCREATEPATTERNBRUSH & 0x00FF):
        validRecordType = true;
        break;
    case (META_SETLAYOUT & 0x00FF):
        validRecordType = true;
        break;
    case (META_SETBKCOLOR & 0x00FF):
        validRecordType = true;
        break;
    case (META_SETTEXTCOLOR & 0x00FF):
        validRecordType = true;
        break;
    case (META_OFFSETVIEWPORTORG & 0x00FF):
        validRecordType = true;
        break;
    case (META_LINETO & 0x00FF):
        validRecordType = true;
        break;
    case (META_MOVETO & 0x00FF):
        validRecordType = true;
        break;
    case (META_OFFSETCLIPRGN & 0x00FF):
        validRecordType = true;
        break;
    case (META_FILLREGION & 0x00FF):
        validRecordType = true;
        break;
    case (META_SETMAPPERFLAGS & 0x00FF):
        validRecordType = true;
        break;
    case (META_SELECTPALETTE & 0x00FF):
        validRecordType = true;
        break;
    case (META_POLYGON & 0x00FF):
        validRecordType = true;
        break;
    case (META_POLYLINE & 0x00FF):
        validRecordType = true;
        break;
    case (META_SETTEXTJUSTIFICATION & 0x00FF):
        validRecordType = true;
        break;
    case (META_SETWINDOWORG & 0x00FF):
        validRecordType = true;
        break;
    case (META_SETWINDOWEXT & 0x00FF):
        validRecordType = true;
        break;
    case (META_SETVIEWPORTORG & 0x00FF):
        validRecordType = true;
        break;
    case (META_SETVIEWPORTEXT & 0x00FF):
        validRecordType = true;
        break;
    case (META_OFFSETWINDOWORG & 0x00FF):
        validRecordType = true;
        break;
    case (META_SCALEWINDOWEXT & 0x00FF):
        validRecordType = true;
        break;
    case (META_SCALEVIEWPORTEXT & 0x00FF):
        validRecordType = true;
        break;
    case (META_EXCLUDECLIPRECT & 0x00FF):
        validRecordType = true;
        break;
    case (META_INTERSECTCLIPRECT & 0x00FF):
        validRecordType = true;
        break;
    case (META_ELLIPSE & 0x00FF):
        validRecordType = true;
        break;
    case (META_FLOODFILL & 0x00FF):
        validRecordType = true;
        break;
    case (META_FRAMEREGION & 0x00FF):
        validRecordType = true;
        break;
    case (META_ANIMATEPALETTE & 0x00FF):
        validRecordType = true;
        break;
    case (META_TEXTOUT & 0x00FF):
        validRecordType = true;
        break;
    case (META_POLYPOLYGON & 0x00FF):
        validRecordType = true;
        break;
    case (META_EXTFLOODFILL & 0x00FF):
        validRecordType = true;
        break;
    case (META_RECTANGLE & 0x00FF):
        validRecordType = true;
        break;
    case (META_SETPIXEL & 0x00FF):
        validRecordType = true;
        break;
    case (META_ROUNDRECT & 0x00FF):
        validRecordType = true;
        break;
    case (META_PATBLT & 0x00FF):
        validRecordType = true;
        break;
    case (META_SAVEDC & 0x00FF):
        validRecordType = true;
        break;
    case (META_PIE & 0x00FF):
        validRecordType = true;
        break;
    case (META_STRETCHBLT & 0x00FF):
        validRecordType = true;
        break;
    case (META_ESCAPE & 0x00FF):
        validRecordType = true;
        break;
    case (META_INVERTREGION & 0x00FF):
        validRecordType = true;
        break;
    case (META_PAINTREGION & 0x00FF):
        validRecordType = true;
        break;
    case (META_SELECTCLIPREGION & 0x00FF):
        validRecordType = true;
        break;
    case (META_SELECTOBJECT & 0x00FF):
        validRecordType = true;
        break;
    case (META_SETTEXTALIGN & 0x00FF):
        validRecordType = true;
        break;
    case (META_ARC & 0x00FF):
        validRecordType = true;
        break;
    case (META_CHORD & 0x00FF):
        validRecordType = true;
        break;
    case (META_BITBLT & 0x00FF):
        validRecordType = true;
        break;
    case (META_EXTTEXTOUT & 0x00FF):
        validRecordType = true;
        break;
    case (META_SETDIBTODEV & 0x00FF):
        validRecordType = true;
        break;
    case (META_DIBBITBLT & 0x00FF):
        validRecordType = true;
        break;
    case (META_DIBSTRETCHBLT & 0x00FF):
        validRecordType = true;
        break;
    case (META_STRETCHDIB & 0x00FF):
        validRecordType = true;
        break;
    case (META_DELETEOBJECT & 0x00FF):
        validRecordType = true;
        break;
    case (META_CREATEPALETTE & 0x00FF):
        validRecordType = true;
        break;
    case (META_CREATEPATTERNBRUSH & 0x00FF):
        validRecordType = true;
        break;
    case (META_CREATEPENINDIRECT & 0x00FF):
        validRecordType = true;
        break;
    case (META_CREATEFONTINDIRECT & 0x00FF):
        validRecordType = true;
        break;
    case (META_CREATEBRUSHINDIRECT & 0x00FF):
        validRecordType = true;
        break;
    case (META_CREATEREGION & 0x00FF):
        validRecordType = true;
        break;
    default:
        validRecordType = false;
    };
    if(!validRecordType)
    {
        throw std::runtime_error("Invalid record function");
    }
}
Beispiel #6
0
WinHelpPhraseFile::WinHelpPhraseFile(QFile &file, qint64 off,
    QTextCodec *codec, bool compressed, bool mvbHint) :
    phrases(), phrasesRaw()
{
    PRINT_DBG("Loading WinHelp phrase file at %lld", off);
    if (codec == NULL)
    {
        throw std::runtime_error("Codec is NULL");
    }
    seekFile(file, off);
    InternalDirectoryFileHeader hdr(file, off);
    if (compressed)
    {
        if (mvbHint)
        {
            seekFile(file, off + InternalDirectoryFileHeader::size);
            quint16 eightHundr = readUnsignedWord(file);
            quint16 nPhr = readUnsignedWord(file);
            quint16 oneHundr = readUnsignedWord(file);
            if ((eightHundr == 0x0800) && (oneHundr == 0x0100) && (nPhr != 0))
            {
                PRINT_DBG(
                    "Loading compressed WinHelp phrase file, MVB alternative");
                seekFile(file, off + InternalDirectoryFileHeader::size);
                quint16 eightHundred = readUnsignedWord(file);
                PRINT_DBG("        Eight hundred: %d", eightHundred);
                quint16 numPhrases = readUnsignedWord(file);
                PRINT_DBG("        Num phrases: %d", numPhrases);
                quint16 oneHundred = readUnsignedWord(file);
                PRINT_DBG("        One hundred: %d", oneHundred);
                if (oneHundred != 0x0100)
                {
                    throw std::runtime_error("Not a WinHelp phrase file");
                }
                quint32 uncompressedSize = readUnsignedDWord(file);
                PRINT_DBG("        Uncompressed size: %d", uncompressedSize);
                for (int i = 0; i < 30; i++)
                {
                    quint8 unused = readUnsignedByte(file);
                    PRINT_DBG("        Unused: %d", unused);
                }
                QScopedArrayPointer<uint> phraseOffset(
                    new uint[static_cast<size_t> (numPhrases + 1)]);
                PRINT_DBG("Reading phrase offsets at %lld", file.pos());
                for (quint16 index = 0; index < numPhrases + 1; index++)
                {
                    phraseOffset[index] = static_cast<uint> (readUnsignedWord(
                            file));
                    PRINT_DBG("        Phrase offset: %d", phraseOffset[index]);
                }
                qint64 inputLength = off + hdr.getReservedSpace() - file.pos();
                PRINT_DBG("Reading compressed phrases at %lld", file.pos());
                QScopedArrayPointer<quint8>
                uncompressedPhrases(
                    new quint8[static_cast<size_t> (uncompressedSize)]);
                unpackLZ77(file, file.pos(), inputLength,
                    uncompressedPhrases.data(),
                    static_cast<size_t> (uncompressedSize));
                size_t pointer = static_cast<size_t> (0);
                for (quint16 index = 0; index < numPhrases; index++)
                {
                    uint size = phraseOffset[index + 1] - phraseOffset[index];
                    QString phrase = readFixedLengthStringFromBuffer(
                        uncompressedPhrases.data(),
                        static_cast<size_t> (uncompressedSize),
                        pointer, size, codec);
                    this->phrases.append(phrase);
                    QScopedArrayPointer<quint8> phraseRaw(
                        new quint8[static_cast<size_t> (size)]);
                    copyBytesFromBuffer(
                        reinterpret_cast<const void *> (uncompressedPhrases.
                            data()),
                        static_cast<size_t> (uncompressedSize),
                        pointer, static_cast<size_t> (size),
                        reinterpret_cast<void *> (phraseRaw.data()),
                        static_cast<size_t> (size));
                    this->phrasesRaw.append(QByteArray(
                            reinterpret_cast<const char *> (phraseRaw.data()),
                            static_cast<int> (size)));
                    pointer += static_cast<size_t> (size);
                    PRINT_DBG("        Phrase: %s", phrase.toLocal8Bit().data());
                }
            }
            else
            {
                PRINT_DBG("Loading compressed WinHelp phrase file");
                seekFile(file, off + InternalDirectoryFileHeader::size);
                quint16 numPhrases = readUnsignedWord(file);
                PRINT_DBG("        Num phrases: %d", numPhrases);
                quint16 oneHundred = readUnsignedWord(file);
                PRINT_DBG("        One hundred: %d", oneHundred);
                if (oneHundred != 0x0100)
                {
                    throw std::runtime_error("Not a WinHelp phrase file");
                }
                quint32 uncompressedSize = readUnsignedDWord(file);
                PRINT_DBG("        Uncompressed size: %d", uncompressedSize);
                QScopedArrayPointer<uint> phraseOffset(
                    new uint[static_cast<size_t> (numPhrases + 1)]);
                PRINT_DBG("Reading phrase offsets at %lld", file.pos());
                for (quint16 index = 0; index < numPhrases + 1; index++)
                {
                    phraseOffset[index] = static_cast<uint> (readUnsignedWord(
                            file));
                    PRINT_DBG("        Phrase offset: %d", phraseOffset[index]);
                }
                PRINT_DBG("Reading compressed phrases at %lld", file.pos());
                qint64 inputLength = off + hdr.getReservedSpace() - file.pos();
                QScopedArrayPointer<quint8>
                uncompressedPhrases(
                    new quint8[static_cast<size_t> (uncompressedSize)]);
                unpackLZ77(file, file.pos(), inputLength,
                    uncompressedPhrases.data(),
                    static_cast<size_t> (uncompressedSize));
                size_t pointer = static_cast<size_t> (0);
                for (quint16 index = 0; index < numPhrases; index++)
                {
                    uint size = phraseOffset[index + 1] - phraseOffset[index];
                    QString phrase = readFixedLengthStringFromBuffer(
                        uncompressedPhrases.data(),
                        static_cast<size_t> (uncompressedSize),
                        pointer, size, codec);
                    this->phrases.append(phrase);
                    QScopedArrayPointer<quint8> phraseRaw(
                        new quint8[static_cast<size_t> (size)]);
                    copyBytesFromBuffer(
                        reinterpret_cast<const void *> (uncompressedPhrases.
                            data()),
                        static_cast<size_t> (uncompressedSize),
                        pointer, static_cast<size_t> (size),
                        reinterpret_cast<void *> (phraseRaw.data()),
                        static_cast<size_t> (size));
                    this->phrasesRaw.append(QByteArray(
                            reinterpret_cast<const char *> (phraseRaw.data()),
                            static_cast<int> (size)));
                    pointer += static_cast<size_t> (size);
                    PRINT_DBG("        Phrase: %s", phrase.toLocal8Bit().data());
                }
            }
        }
        else
        {
            PRINT_DBG("Loading compressed WinHelp phrase file");
            seekFile(file, off + InternalDirectoryFileHeader::size);
            quint16 numPhrases = readUnsignedWord(file);
            PRINT_DBG("        Num phrases: %d", numPhrases);
            quint16 oneHundred = readUnsignedWord(file);
            PRINT_DBG("        One hundred: %d", oneHundred);
            if (oneHundred != 0x0100)
            {
                throw std::runtime_error("Not a WinHelp phrase file");
            }
            quint32 uncompressedSize = readUnsignedDWord(file);
            PRINT_DBG("        Uncompressed size: %d", uncompressedSize);
            QScopedArrayPointer<uint> phraseOffset(
                new uint[static_cast<size_t> (numPhrases + 1)]);
            PRINT_DBG("Reading phrase offsets at %lld", file.pos());
            for (quint16 index = 0; index < numPhrases + 1; index++)
            {
                phraseOffset[index]
                    = static_cast<uint> (readUnsignedWord(file));
                PRINT_DBG("        Phrase offset: %d", phraseOffset[index]);
            }
            PRINT_DBG("Reading compressed phrases at %lld", file.pos());
            qint64 inputLength = off + hdr.getReservedSpace() - file.pos();
            QScopedArrayPointer<quint8> uncompressedPhrases(
                new quint8[static_cast<size_t> (uncompressedSize)]);
            unpackLZ77(file, file.pos(), inputLength,
                uncompressedPhrases.data(),
                static_cast<size_t> (uncompressedSize));
            size_t pointer = static_cast<size_t> (0);
            for (quint16 index = 0; index < numPhrases; index++)
            {
                uint size = phraseOffset[index + 1] - phraseOffset[index];
                QString phrase = readFixedLengthStringFromBuffer(
                    uncompressedPhrases.data(),
                    static_cast<size_t> (uncompressedSize), pointer,
                    size, codec);
                this->phrases.append(phrase);
                QScopedArrayPointer<quint8> phraseRaw(
                    new quint8[static_cast<size_t> (size)]);
                copyBytesFromBuffer(
                    reinterpret_cast<const void *> (uncompressedPhrases.data()),
                    static_cast<size_t> (uncompressedSize), pointer,
                    static_cast<size_t> (size),
                    reinterpret_cast<void *> (phraseRaw.data()),
                    static_cast<size_t> (size));
                this->phrasesRaw.append(QByteArray(
                        reinterpret_cast<const char *> (phraseRaw.data()),
                        static_cast<int> (size)));
                pointer += static_cast<size_t> (size);
                PRINT_DBG("        Phrase: %s", phrase.toLocal8Bit().data());
            }
        }
    }
    else
    {
        PRINT_DBG("Loading uncompressed WinHelp phrase file");
        seekFile(file, off + InternalDirectoryFileHeader::size);
        quint16 numPhrases = readUnsignedWord(file);
        PRINT_DBG("        Num phrases: %d", numPhrases);
        quint16 oneHundred = readUnsignedWord(file);
        PRINT_DBG("        One hundred: %d", oneHundred);
        if (oneHundred != 0x0100)
        {
            throw std::runtime_error("Not a WinHelp phrase file");
        }
        QScopedArrayPointer<uint> phraseOffset(
            new uint[static_cast<size_t> (numPhrases + 1)]);
        PRINT_DBG("Reading phrase offsets at %lld", file.pos());
        for (quint16 index = 0; index < numPhrases + 1; index++)
        {
            phraseOffset[index] = static_cast<uint> (readUnsignedWord(file));
            PRINT_DBG("        Phrase offset: %d", phraseOffset[index]);
        }
        PRINT_DBG("Reading phrases at %lld", file.pos());
        for (quint16 index = 0; index < numPhrases; index++)
        {
            uint size = phraseOffset[index + 1] - phraseOffset[index];
            qint64 posMem = file.pos();
            QString phrase = readFixedLengthString(file, size, codec);
            this->phrases.append(phrase);
            QScopedArrayPointer<quint8> phraseRaw(
                new quint8[static_cast<size_t> (size)]);
            seekFile(file, posMem);
            fillBuffer(file, static_cast<qint64> (size),
                reinterpret_cast<void *> (phraseRaw.data()),
                static_cast<size_t> (size));
            this->phrasesRaw.append(QByteArray(
                    reinterpret_cast<const char *> (phraseRaw.data()),
                    static_cast<int> (size)));
            PRINT_DBG("        Phrase: %s", phrase.toLocal8Bit().data());
        }
    }
    PRINT_DBG("WinHelp phrase file loaded successfully");
}
Beispiel #7
0
static unsigned long long readUnsignedQWord(ZLInputStream &stream) {
	unsigned long long lowPart = readUnsignedDWord(stream);
	unsigned long long highPart = readUnsignedDWord(stream);
	return (highPart << 32) + lowPart;
}
Beispiel #8
0
bool CHMFileInfo::init(ZLInputStream &stream) {
	{
		// header start
		if (readString(stream, 4) != "ITSF") {
			return false;
		}

		unsigned long version = readUnsignedDWord(stream);

		// DWORD total length
		// DWORD unknown
		// DWORD timestamp
		// DWORD language id
		// 0x10 bytes 1st GUID
		// 0x10 bytes 2nd GUID
		// QWORD section 0 offset
		// QWORD section 0 length
		stream.seek(4 * 4 + 2 * 0x10 + 2 * 8, false);
		
		unsigned long long sectionOffset1 = readUnsignedQWord(stream);
		unsigned long long sectionLength1 = readUnsignedQWord(stream);
		mySection0Offset = sectionOffset1 + sectionLength1;
		// header end

		// additional header data start
		if (version > 2) {
			mySection0Offset = readUnsignedQWord(stream);
		}
		// additional header data end

		stream.seek(sectionOffset1, true);
		// header section 1 start
		// directory header start
		if (readString(stream, 4) != "ITSP") {
			return false;
		}

		// DWORD version
		// DWORD length
		// DWORD 0x000A
		// DWORD chunk size
		// DWORD density
		// DWORD depth
		// DWORD root chunk number
		// DWORD first chunk number
		// DWORD last chunk number
		// DWORD -1
		stream.seek(10 * 4, false);
		unsigned long dirChunkNumber = readUnsignedDWord(stream);
		// ...
		stream.seek(36, false);
		// header section 1 end

		std::size_t nextOffset = stream.offset();
		for (unsigned long i = 0; i < dirChunkNumber; ++i) {
			nextOffset += 4096;
			std::string header = readString(stream, 4);
			if (header == "PMGL") {
				unsigned long quickRefAreaSize = readUnsignedDWord(stream) % 4096;
				stream.seek(12, false);
				std::size_t startOffset = stream.offset();
				std::size_t oldOffset = startOffset;
				while (startOffset < nextOffset - quickRefAreaSize) {
					int nameLength = readEncodedInteger(stream);
					std::string name = readString(stream, nameLength);
					int contentSection = readEncodedInteger(stream);
					int offset = readEncodedInteger(stream);
					int length = readEncodedInteger(stream);
					if (name.substr(0, 2) != "::") {
						name = ZLUnicodeUtil::toLower(name);
					}
					myRecords.insert(
						std::make_pair(
							name,
							CHMFileInfo::RecordInfo(contentSection, offset, length)
						)
					);
					startOffset = stream.offset();
					if (oldOffset == startOffset) {
						break;
					}
					oldOffset = startOffset;
				}
			} else if (header == "PMGI") {
				unsigned long quickRefAreaSize = readUnsignedDWord(stream);
				std::size_t startOffset = stream.offset();
				std::size_t oldOffset = startOffset;
				while (startOffset < nextOffset - quickRefAreaSize) {
					int nameLength = readEncodedInteger(stream);
					std::string name = readString(stream, nameLength);
					// chunk number
					readEncodedInteger(stream);
					startOffset = stream.offset();
					if (oldOffset == startOffset) {
						break;
					}
					oldOffset = startOffset;
				}
			}
			stream.seek(nextOffset, true);
			if (stream.offset() != nextOffset) {
				break;
			}
		}
	}

	{
		if (!moveToEntry(stream, "::DataSpace/NameList")) {
			return false;
		}
		stream.seek(2, false);
		const int sectionNumber = readUnsignedWord(stream);
		for (int i = 0; i < sectionNumber; ++i) {
			const int length = readUnsignedWord(stream);
			std::string sectionName;
			sectionName.reserve(length);
			for (int j = 0; j < length; ++j) {
				sectionName += (char)readUnsignedWord(stream);
			}
			stream.seek(2, false);
			mySectionNames.push_back(sectionName);
		}
	}

	{
		for (unsigned int i = 1; i < mySectionNames.size(); ++i) {
			RecordMap::const_iterator it =
				myRecords.find("::DataSpace/Storage/" + mySectionNames[i] + "/Content");
			if (it == myRecords.end()) {
				return false;
			}
			RecordInfo recordInfo = it->second;
			if (recordInfo.Section != 0) {
				return false;
			}
			mySectionInfos.push_back(SectionInfo());
			SectionInfo &info = mySectionInfos.back();
			info.Offset = mySection0Offset + recordInfo.Offset;
			info.Length = recordInfo.Length;

			if (!moveToEntry(stream, "::DataSpace/Storage/" + mySectionNames[i] + "/ControlData")) {
				return false;
			}
			stream.seek(4, false);
			std::string lzxc = readString(stream, 4);
			if (lzxc != "LZXC") {
				return false;
			}
			const int version = readUnsignedDWord(stream);
			if ((version <= 0) || (version > 2)) {
				return false;
			}
			info.ResetInterval = readUnsignedDWord(stream);
			if (version == 1) {
				info.ResetInterval /= 0x8000;
			}
			info.WindowSizeIndex = (version == 1) ? 0 : 15;
			{
				int ws = readUnsignedDWord(stream);
				if (ws > 0) {
					while ((ws & 1) == 0) {
						ws >>= 1;
						info.WindowSizeIndex++;
					}
				}
			}

			if (!moveToEntry(stream, "::DataSpace/Storage/" + mySectionNames[i] + "/Transform/{7FC28940-9D31-11D0-9B27-00A0C91E9C7C}/InstanceData/ResetTable")) {
				return false;
			}
			stream.seek(4, false);
			const std::size_t entriesNumber = readUnsignedDWord(stream);
			if (entriesNumber == 0) {
				return false;
			}
			if (entriesNumber > 2048) {
				// file size is greater than 60 Mb
				return false;
			}
			info.ResetTable.reserve(entriesNumber);
			stream.seek(8, false);
			info.UncompressedSize = readUnsignedQWord(stream);
			if ((info.UncompressedSize - 1) / 0x8000 != entriesNumber - 1) {
				return false;
			}
			info.CompressedSize = readUnsignedQWord(stream);
			stream.seek(8, false);
			std::size_t previous = 0;
			for (std::size_t j = 0; j < entriesNumber; ++j) {
				std::size_t value = readUnsignedQWord(stream);
				if ((j > 0) == (value <= previous)) {
					return false;
				}
				info.ResetTable.push_back(value);
				previous = value;
			}
		}
	}

	return true;
}
Beispiel #9
0
WinHelpIcon::WinHelpIcon(QFile &file, qint64 off) :
    images()
{
    PRINT_DBG("Loading icon");
    seekFile(file, off);
    quint16 magicIn = readUnsignedWord(file);
    if (magicIn != 0)
    {
        throw std::runtime_error("Not an icon resource header");
    }
    PRINT_DBG("        Icon resource header magic: %d", magicIn);
    quint16 resourceTypeIn = readUnsignedWord(file);
    if (resourceTypeIn != 1)
    {
        throw std::runtime_error("Resource is not an icon");
    }
    PRINT_DBG("        Icon resource header resource type: %d", resourceTypeIn);
    quint16 imagesCountIn = readUnsignedWord(file);
    PRINT_DBG("        Icon resource header images count: %d", imagesCountIn);
    QScopedArrayPointer<quint8> widths(new quint8[imagesCountIn]);
    QScopedArrayPointer<quint8> heights(new quint8[imagesCountIn]);
    QScopedArrayPointer<quint32> colorCounts(new quint32[imagesCountIn]);
    QScopedArrayPointer<quint16> colorPlanes(new quint16[imagesCountIn]);
    QScopedArrayPointer<quint16> bitsPerPixelCount(new quint16[imagesCountIn]);
    QScopedArrayPointer<qint64> bitmapSizes(new qint64[imagesCountIn]);
    QScopedArrayPointer<qint64> bitmapOffsets(new qint64[imagesCountIn]);
    for (int index = 0; index < imagesCountIn; index++)
    {
        widths[index] = readUnsignedByte(file);
        PRINT_DBG("        Icon image directory image header width: %d",
            widths[index]);
        heights[index] = readUnsignedByte(file);
        PRINT_DBG("        Icon image directory image header height: %d",
            heights[index]);
        colorCounts[index] = static_cast<quint32> (readUnsignedByte(file));
        PRINT_DBG("        Icon image directory image header color count: %d",
            colorCounts[index]);
        quint8 reservedIn = readUnsignedByte(file);
        if (reservedIn != 0)
        {
            qDebug()
            << "Icon image directory image header reserved value is non-zero";
        }
        PRINT_DBG("        Icon image directory image header reserved: %d",
            reservedIn);
        colorPlanes[index] = readUnsignedWord(file);
        PRINT_DBG("        Icon image directory image header color planes: %d",
            colorPlanes[index]);
        bitsPerPixelCount[index] = readUnsignedWord(file);
        PRINT_DBG(
            "        Icon image directory image header bits per pixel count: %d",
            bitsPerPixelCount[index]);
        bitmapSizes[index] = static_cast<qint64> (readUnsignedDWord(file));
        PRINT_DBG("        Icon image directory image header bitmap size: %lld",
            bitmapSizes[index]);
        bitmapOffsets[index] = static_cast<qint64> (readUnsignedDWord(file));
        PRINT_DBG(
            "        Icon image directory image header bitmap offset: %lld",
            bitmapOffsets[index]);
    }
    for (int index = 0; index < imagesCountIn; index++)
    {
        seekFile(file, off + bitmapOffsets[index]);
        quint32 headerSizeIn = readUnsignedDWord(file);
        PRINT_DBG("        Icon image header size: %d", headerSizeIn);
        if (headerSizeIn == 40)
        {
            qint32 widthIn = readSignedDWord(file);
            PRINT_DBG("        Icon image width: %d", widthIn);
            qint64 realWidth = static_cast<qint64> (widths[index]);
            if (realWidth == 0)
            {
                realWidth = static_cast<qint64> (widthIn);
            }
            qint32 heightIn = readSignedDWord(file);
            PRINT_DBG("        Icon image height: %d", heightIn);
            qint64 realHeight = static_cast<qint64> (heights[index]);
            if (realHeight == 0)
            {
                realHeight = (static_cast<qint64> (heightIn)) / (Q_INT64_C(2));
            }
            quint16 colorPlanesIn = readUnsignedWord(file);
            PRINT_DBG("        Icon image color planes: %d", colorPlanesIn);
            quint16 bitsPerPixelCountIn = readUnsignedWord(file);
            PRINT_DBG("        Icon image bits per pixel count: %d",
                bitsPerPixelCountIn);
            if (colorCounts[index] == 0)
            {
                if (colorPlanesIn == 1)
                {
                    if (bitsPerPixelCountIn == 1)
                    {
                        colorCounts[index] = 2;
                    }
                    else
                    {
                        if (bitsPerPixelCountIn == 4)
                        {
                            colorCounts[index] = 16;
                        }
                        else
                        {
                            if (bitsPerPixelCountIn == 8)
                            {
                                colorCounts[index] = 256;
                            }
                            else
                            {
                                if (bitsPerPixelCountIn != 32)
                                {
                                    colorCounts[index] = 1
                                        << bitsPerPixelCountIn;
                                }
                            }
                        }
                    }
                }
                else
                {
                    colorCounts[index] = 1 << (bitsPerPixelCountIn
                        * colorPlanesIn);
                }
            }
            quint32 compressionMethodIn = readUnsignedDWord(file);
            PRINT_DBG("        Icon image compression method: %d",
                compressionMethodIn);
            quint32 imageSizeIn = readUnsignedDWord(file);
            PRINT_DBG("        Icon image size: %d", imageSizeIn);
            qint32 horizontalResolutionIn = readSignedDWord(file);
            PRINT_DBG("        Icon image horizontal resolution: %d",
                horizontalResolutionIn);
            qint32 verticalResolutionIn = readSignedDWord(file);
            PRINT_DBG("        Icon image vertical resolution: %d",
                verticalResolutionIn);
            quint32 colorsInPaletteIn = readUnsignedDWord(file);
            PRINT_DBG("        Icon image colors in palette: %d",
                colorsInPaletteIn);
            quint32 importantColorsUsedIn = readUnsignedDWord(file);
            PRINT_DBG("        Icon image imporatnt colors used: %d",
                importantColorsUsedIn);
            if ((realWidth != 0) && (realHeight != 0) && ((colorCounts[index]
                        == 0) || (colorCounts[index] == 2) ||
                        (colorCounts[index]
                        == 16) || (colorCounts[index] == 256)))
            {
                QImage image(static_cast<int> (realWidth),
                    static_cast<int> (realHeight), QImage::Format_ARGB32);
                if (colorCounts[index] == 2)
                {
                    QScopedArrayPointer<QRgb> palette(new QRgb[2]);
                    for (int i = 0; i < 2; i++)
                    {
                        palette[i] = readBGRDword(file);
                    }
                    qint64 scanlineBytes = ((realWidth + Q_INT64_C(31))
                        / (Q_INT64_C(32))) * Q_INT64_C(4);
                    QScopedArrayPointer<quint8> xorImage(
                        new quint8[scanlineBytes * realHeight]);
                    QScopedArrayPointer<quint8> andImage(
                        new quint8[scanlineBytes * realHeight]);
                    if (file.read(reinterpret_cast<char *> (xorImage.data()),
                                (scanlineBytes * realHeight)) != (scanlineBytes
                            * realHeight))
                    {
                        throw std::runtime_error("Unable to read icon image");
                    }
                    if (file.read(reinterpret_cast<char *> (andImage.data()),
                                (scanlineBytes * realHeight)) != (scanlineBytes
                            * realHeight))
                    {
                        throw std::runtime_error("Unable to read icon image");
                    }
                    quint8 masks[] =
                    {
                        128, 64, 32, 16, 8, 4, 2, 1
                    };
                    for (qint64 row = 0; row < realHeight; row++)
                    {
                        for (qint64 col = 0; col < realWidth; col++)
                        {
                            int colorIndex = 0;
                            if ((xorImage[row * scanlineBytes + col
                                        / (Q_INT64_C(8))] & masks[col
                                        % (Q_INT64_C(8))]) != 0)
                            {
                                colorIndex = 1;
                            }
                            else
                            {
                                colorIndex = 0;
                            }
                            if ((andImage[row * scanlineBytes + col
                                        / (Q_INT64_C(8))] & masks[col
                                        % (Q_INT64_C(8))]) != 0)
                            {
                                image.setPixel(col, realHeight - Q_INT64_C(1)
                                    - row, qRgba(qRed(palette[colorIndex]),
                                        qGreen(palette[colorIndex]), qBlue(
                                            palette[colorIndex]), 0));
                            }
                            else
                            {
                                image.setPixel(col, realHeight - Q_INT64_C(1)
                                    - row, qRgba(qRed(palette[colorIndex]),
                                        qGreen(palette[colorIndex]), qBlue(
                                            palette[colorIndex]), 0xFF));
                            }
                        }
                    }
                }
                else
                {
                    if (colorCounts[index] == 16)
                    {
                        QScopedArrayPointer<QRgb> palette(new QRgb[16]);
                        for (int i = 0; i < 16; i++)
                        {
                            palette[i] = readBGRDword(file);
                        }
                        qint64 scanlineBytesXor = ((realWidth * Q_INT64_C(4)
                                + Q_INT64_C(31)) / (Q_INT64_C(32)))
                            * Q_INT64_C(4);
                        qint64 scanlineBytesAnd = ((realWidth + Q_INT64_C(31))
                            / (Q_INT64_C(32))) * Q_INT64_C(4);
                        QScopedArrayPointer<quint8> xorImage(
                            new quint8[scanlineBytesXor * realHeight]);
                        QScopedArrayPointer<quint8> andImage(
                            new quint8[scanlineBytesAnd * realHeight]);
                        if (file.read(
                                reinterpret_cast<char *> (xorImage.data()),
                                    (scanlineBytesXor * realHeight))
                            != (scanlineBytesXor * realHeight))
                        {
                            throw std::runtime_error(
                                "Unable to read icon image");
                        }
                        if (file.read(
                                reinterpret_cast<char *> (andImage.data()),
                                    (scanlineBytesAnd * realHeight))
                            != (scanlineBytesAnd * realHeight))
                        {
                            throw std::runtime_error(
                                "Unable to read icon image");
                        }
                        quint8 masks[] =
                        {
                            128, 64, 32, 16, 8, 4, 2, 1
                        };
                        for (qint64 row = 0; row < realHeight; row++)
                        {
                            for (qint64 col = 0; col < realWidth; col++)
                            {
                                quint8 colorIndex = 0;
                                if ((col & Q_INT64_C(1)) == Q_INT64_C(0))
                                {
                                    colorIndex = xorImage[row
                                        * scanlineBytesXor + col
                                        / Q_INT64_C(2)];
                                    colorIndex = colorIndex >> 4;
                                }
                                else
                                {
                                    colorIndex = xorImage[row
                                        * scanlineBytesXor + col
                                        / Q_INT64_C(2)] & 15;
                                }
                                if ((andImage[row * scanlineBytesAnd + col
                                            / (Q_INT64_C(8))] & masks[col
                                            % (Q_INT64_C(8))]) != 0)
                                {
                                    image.setPixel(
                                        col,
                                        realHeight - Q_INT64_C(1) - row,
                                        qRgba(
                                            qRed(
                                                palette[static_cast<int> (
                                                        colorIndex)]),
                                            qGreen(
                                                palette[static_cast<int> (
                                                        colorIndex)]),
                                            qBlue(
                                                palette[static_cast<int> (
                                                        colorIndex)]),
                                            0));
                                }
                                else
                                {
                                    image.setPixel(
                                        col,
                                        realHeight - Q_INT64_C(1) - row,
                                        qRgba(
                                            qRed(
                                                palette[static_cast<int> (
                                                        colorIndex)]),
                                            qGreen(
                                                static_cast<int> (palette[
                                                        colorIndex])),
                                            qBlue(
                                                palette[static_cast<int> (
                                                        colorIndex)]),
                                            0xFF));
                                }
                            }
                        }
                    }
WinHelpPhrIndexFile::WinHelpPhrIndexFile(QFile &file, qint64 off) :
    phrasesOffset(), phrasesBits()
{
    PRINT_DBG("Loading WinHelp PhrIndex file at %lld", off);
    seekFile(file, off);
    InternalDirectoryFileHeader hdr(file, off);
    seekFile(file, off + InternalDirectoryFileHeader::size);
    quint32 magic = readUnsignedDWord(file);
    PRINT_DBG("        Magic: %d", magic);
    if (magic != 1)
    {
        throw std::runtime_error("Not a PhrIndex file");
    }
    quint32 nEntries = readUnsignedDWord(file);
    PRINT_DBG("        nEntries: %d", nEntries);
    quint32 compressedSize = readUnsignedDWord(file);
    PRINT_DBG("        Compressed size: %d", compressedSize);
    this->phrImageSize = static_cast<qint64> (readUnsignedDWord(file));
    PRINT_DBG("        phrImage size: %lld", this->phrImageSize);
    this->phrImageCompressedSize
        = static_cast<qint64> (readUnsignedDWord(file));
    PRINT_DBG("        phrImage compressed size: %lld",
        this->phrImageCompressedSize);
    quint32 alwaysZero = readUnsignedDWord(file);
    PRINT_DBG("        Always zero: %d", alwaysZero);
    if (alwaysZero != 0)
    {
        qDebug() << "Always zero phrIndex file field is non zero";
    }
    quint8 bitfieldL = readUnsignedByte(file);
    PRINT_DBG("        Bitfield low byte: %d", bitfieldL);
    quint8 bitfieldH = readUnsignedByte(file);
    PRINT_DBG("        Bitfield high byte: %d", bitfieldH);
    quint8 bitCount = bitfieldL & 0x0F;
    PRINT_DBG("        Bitcount: %d", bitCount);
    quint16 unknownValue = readUnsignedWord(file);
    PRINT_DBG("        Unknown value: %d", unknownValue);
    this->phrasesOffset.resize(nEntries + 1);
    this->phrasesOffset[0] = 0;
    PRINT_DBG("        Phrase offset: %d", this->phrasesOffset[0]);
    IntAllignedCursor cur;
    cur.currentBitIndex = 0;
    cur.currentDwordByte0 = 0;
    cur.currentDwordByte1 = 0;
    cur.currentDwordByte2 = 0;
    cur.currentDwordByte3 = 0;
    for (quint32 i = 0; i < nEntries; i++)
    {
        uint n = 1;
        while (this->getNextBitIntAlligned(file, cur))
        {
            n += static_cast<uint> (0x0001 << bitCount);
        }
        if (this->getNextBitIntAlligned(file, cur))
        {
            n += 1;
        }
        if (bitCount > 1)
        {
            if (this->getNextBitIntAlligned(file, cur))
            {
                n += 2;
            }
        }
        if (bitCount > 2)
        {
            if (this->getNextBitIntAlligned(file, cur))
            {
                n += 4;
            }
        }
        if (bitCount > 3)
        {
            if (this->getNextBitIntAlligned(file, cur))
            {
                n += 8;
            }
        }
        if (bitCount > 4)
        {
            if (this->getNextBitIntAlligned(file, cur))
            {
                n += 16;
            }
        }
        this->phrasesOffset[i + 1] = this->phrasesOffset[i] + n;
        PRINT_DBG("        Phrase offset: %d", this->phrasesOffset[i + 1]);
    }
    this->phrasesBits.resize(nEntries);
    ByteAllignedCursor bCur;
    bCur.currentBitIndex = 0;
    bCur.currentByte = 0;
    for (quint32 index = 0; index < nEntries; index++)
    {
        if (this->getNextBitByteAlligned(file, bCur))
        {
            this->phrasesBits[index] = true;
            PRINT_DBG("        Phrase bit is true");
        }
        else
        {
            this->phrasesBits[index] = false;
            PRINT_DBG("        Phrase bit is false");
        }
    }
    PRINT_DBG("WinHelp PhrIndex file loaded successfully");
}