Exemplo n.º 1
0
/*
 *  This function reads a file and verify if it is a legit MPQ archive
 *  or not. Then it fills the mpq_header structure and reads the hash
 *  table.
 */
int libmpq_archive_open(mpq_archive *mpq_a, unsigned char *mpq_filename) {
	int fd = 0;
	int rb = 0;
	int ncnt = FALSE;
	struct stat fileinfo;

	/* allocate memory */
	mpq_a->mpq_l = (mpq_list *)malloc(sizeof(mpq_list));
	memset(mpq_a->mpq_l, 0, sizeof(mpq_list));
	mpq_a->header = (mpq_header *)malloc(sizeof(mpq_header));
	memset(mpq_a->header, 0, sizeof(mpq_header));

	/* Check if file exists and is readable */
	fd = _open((char *)mpq_filename, MPQ_FILE_OPEN_FLAGS);
	if (fd == LIBMPQ_EFILE) {
		return LIBMPQ_EFILE;
	}

	/* fill the structures with informations */
	strcpy((char *)mpq_a->filename, (char *)mpq_filename);
	libmpq_init_buffer(mpq_a);
	mpq_a->fd               = fd;
	mpq_a->header->id       = 0;
	mpq_a->maxblockindex    = 0;
	mpq_a->mpq_l->mpq_files = NULL;

    mpq_a->mpqpos = 0; //k

	while (!ncnt) {
		mpq_a->header->id = 0;
		#ifdef WIN32
			_lseeki64(mpq_a->fd, mpq_a->mpqpos, SEEK_SET);
		#else
			lseek64(mpq_a->fd, mpq_a->mpqpos, SEEK_SET);
		#endif
		rb = _read(mpq_a->fd, mpq_a->header, sizeof(mpq_header));

		/* if different number of bytes read, break the loop */
		if (rb != sizeof(mpq_header)) {
			return LIBMPQ_EFILE_FORMAT;
		}

		/* special offset for protected MPQs */
		if (mpq_a->header->offset == LIBMPQ_HEADER_W3M) {
			mpq_a->flags |= LIBMPQ_FLAG_PROTECTED;
			mpq_a->header->offset = sizeof(mpq_header);
		}

		/* if valid signature has been found, break the loop */
        if (mpq_a->header->id == LIBMPQ_ID_MPQ) {
            ncnt = true;
        }
        /*if (mpq_a->header->id == LIBMPQ_ID_MPQ &&
		    mpq_a->header->offset == sizeof(mpq_header) &&
		    mpq_a->header->hashtablepos < mpq_a->header->archivesize &&
		    mpq_a->header->blocktablepos < mpq_a->header->archivesize) {
			ncnt = TRUE;
		}*/

		/* move to the next possible offset */
		if (!ncnt) {
			mpq_a->mpqpos += 0x200;
		}
	}

	/* get the right positions of the hash table and the block table. */
	mpq_a->blocksize = (0x200 << mpq_a->header->blocksize);
	fstat(mpq_a->fd, &fileinfo);

	/* Normal MPQs must have position of */
	/*if (mpq_a->header->hashtablepos + mpq_a->mpqpos < fileinfo.st_size &&
	    mpq_a->header->blocktablepos + mpq_a->mpqpos < fileinfo.st_size) {
		mpq_a->header->hashtablepos  += mpq_a->mpqpos;
		mpq_a->header->blocktablepos += mpq_a->mpqpos;
	} else {
		return LIBMPQ_EFILE_FORMAT;
	}*/

	/* Try to read and decrypt the hashtable */
	if (libmpq_read_hashtable(mpq_a) != 0) {
		return LIBMPQ_EHASHTABLE;
	}

	/* Try to read and decrypt the blocktable */
	if (libmpq_read_blocktable(mpq_a) != 0) {
		return LIBMPQ_EBLOCKTABLE;
	}

	return LIBMPQ_TOOLS_SUCCESS;
}
Exemplo n.º 2
0
/*
 *  This function reads a file and verify if it is a legit MPQ archive
 *  or not. Then it fills the mpq_header structure and reads the hash
 *  table.
 */
int libmpq_archive_open(mpq_archive *mpq_a, unsigned char *mpq_filename) {
	int fd = 0;
	int rb = 0;
	int ncnt = FALSE;
	struct stat fileinfo;

	memset((void*)mpq_a, 0, sizeof(mpq_archive));

	/* allocate memory */
	mpq_a->header = static_cast<mpq_header*>(malloc(sizeof(mpq_header)));
	memset(mpq_a->header, 0, sizeof(mpq_header));

	/* Check if file exists and is readable */
	fd = open((const char*)mpq_filename, O_RDONLY|O_BINARY);
	if (fd == LIBMPQ_EFILE) {
		return LIBMPQ_EFILE;
	}

	/* fill the structures with informations */
	strncpy((char*)mpq_a->filename, (const char*)mpq_filename, strlen((const char*)mpq_filename));
	libmpq_init_buffer(mpq_a);
	mpq_a->fd               = fd;
	mpq_a->header->id       = 0;
	mpq_a->maxblockindex    = 0;
	mpq_a->header->offset	= 0;

	while (!ncnt) {
		mpq_a->header->id = 0;

		//lseek(mpq_a->fd, mpq_a->mpqpos, SEEK_SET);
		// Fixed support for large / 64bit addresses
		_lseeki64(mpq_a->fd, mpq_a->mpqpos, SEEK_SET);

		rb = read(mpq_a->fd, mpq_a->header, sizeof(mpq_header));

		/* if different number of bytes read, break the loop */
		if (rb != sizeof(mpq_header)) {
			return LIBMPQ_EFILE_FORMAT;
		}

		/* special offset for protected MPQs */
		if (mpq_a->header->offset == LIBMPQ_HEADER_W3M) {
			mpq_a->flags |= LIBMPQ_FLAG_PROTECTED;
			mpq_a->header->offset = sizeof(mpq_header);
		}

		/* if valid signature has been found, break the loop */
		if (mpq_a->header->id == LIBMPQ_ID_MPQ && mpq_a->header->hashtablepos < mpq_a->header->archivesize && mpq_a->header->blocktablepos < mpq_a->header->archivesize) { // && mpq_a->header->offset == sizeof(mpq_header)
			ncnt = TRUE;
		}

		/* move to the next possible offset */
		if (!ncnt) {
			mpq_a->mpqpos += 0x200;
		}
	}

	if (mpq_a->header->offset != sizeof(mpq_header)) {
		//lseek(mpq_a->fd, mpq_a->header->offset, SEEK_SET);
		// Fixed support for large / 64bit addresses
		_lseeki64(mpq_a->fd, mpq_a->header->offset, SEEK_SET);
	}

	/* get the right positions of the hash table and the block table. */
	mpq_a->blocksize = (0x200 << mpq_a->header->blocksize);
	fstat(mpq_a->fd, &fileinfo);

	/* Normal MPQs must have position of */
	if ((mpq_a->header->hashtablepos + mpq_a->mpqpos < (unsigned int)fileinfo.st_size) && (mpq_a->header->blocktablepos + mpq_a->mpqpos < (unsigned int)fileinfo.st_size)) {
		mpq_a->header->hashtablepos  += mpq_a->mpqpos;
		mpq_a->header->blocktablepos += mpq_a->mpqpos;
	} else {
		return LIBMPQ_EFILE_FORMAT;
	}

	/* Try to read and decrypt the hashtable */
	if (libmpq_read_hashtable(mpq_a) != 0) {
		return LIBMPQ_EHASHTABLE;
	}

	/* Try to read and decrypt the blocktable */
	if (libmpq_read_blocktable(mpq_a) != 0) {
		return LIBMPQ_EBLOCKTABLE;
	}

	return LIBMPQ_TOOLS_SUCCESS;
}