char filenames[fcount][16];
You're declaring a variable-length array here. It's not standard C89 to do that. If I were you I'd just declare the array as
char filenames[MAX_FCOUNT][16];
Also:
//Loop through the file names
for(i = F_SIZE + 4; i < F_SIZE + 4 + (fcount * 16); i+=16)
{
fseek(self, i, SEEK_SET);
fread(&filenames[i][16], 16, 1, self);
}
All that seeking is unnecessary. The filenames are all contiguous in the file, so just read the first, then the second, and so on. After reading one filename, your file pointer will already be in the correct position to read the next.
Is there a way to determine EOF without having a table of lengths?
Not really, no.
How are you generating this executable? Because you'll have to add some stuff onto the end to make it work.
I should mention that in doing so, you may mess up the executable format. I'm not very familiar with the windows executable format, but it may require some data at the end of the file (and by adding onto the end of the file, you may be messing it up). A quick way to test this would be to add random junk onto the end of an existing, working program, and see if that crashes it.