/* * 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; }
/* * 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; }