# Solved: Tip or tool to distingush 16/32/64 bit .exe files?



## Riverglen (Aug 29, 2006)

Is there any simple way to determine whether a .exe or .lib file was compiled as a 16 bit vs 32 bit vs 64 bit module? I have several very old programs and libraries that are still important to me, but in some cases I don't know whether they are 16 bit or 32 bit code. (And, if you're curious, I still have my stone axe too.)


----------



## mt2002 (Sep 14, 2005)

Hello,

I am unaware of any tool -- but it most certainly is possible to write a program to test it. Because you have not provided requirements, I cannot provide much more information then that.

The process would just require examining of the executable headers: if optional_header exists, its a 32bit or 64bit exe. if not, its 16bit. optional_header->flags can tell you if its 32bit or 64bit. I can provide source code in C if requested.


----------



## Riverglen (Aug 29, 2006)

Thanks for your interest. My basic problem is that I am not familiar with the structure of an .exe file, so I don't know how to interpret the differences you are referring to. My motivation is that now that the world seems to be in a mindless headlong rush to a 64 bit world, the 16 bit programs I still use are soon to be historical curiosities. It would be more than sufficient for me to have a tool that would take a file name as an argument and return a simple report like "This is a 16 bit app". I don't doubt that I could write it myself if I knew more about the structure of the executable headers you refer to. Source code would be great, but a reference to the information would be sufficient.


----------



## DoubleHelix (Dec 10, 2004)

Unless the program is a stand-alone EXE, there's much more to the program than the executable that launches it. I highly doubt there'd be a way to perform a simple check against one file.


----------



## mt2002 (Sep 14, 2005)

Hello,

The following detects executable type for 16bit and 32bit. Possibly 64bit, dont have a way to test it... please let me know if it works.

```
#include <windows.h>
#include <stdio.h>

typedef enum _imageType {
	IMAGE_16BIT = 0,
	IMAGE_32BIT,
	IMAGE_64BIT,
	IMAGE_UNKNOWN

}imageType;

char* _imageTypeStr [] = {
	"16 bit",
	"32 bit",
	"64 bit",
	"Unknown"
};

void dispImageType (imageType t) {

	if (t<=IMAGE_UNKNOWN)
		printf ("%s", _imageTypeStr[t]);
}

FILE* locateImage (char* imagePath) {

	FILE* pFile = 0;
	if (!imagePath)
		return 0;

	pFile = fopen (imagePath, "rb");
	if (!pFile)
		return 0;

	return pFile;
}

imageType determinType (unsigned char* pImage) {

	IMAGE_DOS_HEADER* lpDosHeader = (IMAGE_DOS_HEADER*)pImage;
	IMAGE_NT_HEADERS* lpNtHeaders = (IMAGE_NT_HEADERS*)
		(lpDosHeader->e_lfanew + pImage);

	if (!lpDosHeader && lpDosHeader->e_magic != 0x5a4d)
		return IMAGE_UNKNOWN;

	//! validate if ptr can be read without error
	//! assumes stub program is < 256 bytes
	if ( (unsigned char*)lpNtHeaders < pImage+0xd0
			|| (unsigned char*)lpNtHeaders > pImage+0x100)
		return IMAGE_16BIT;

	if (lpNtHeaders->Signature!=0x4550)
		return IMAGE_16BIT;

	if (lpNtHeaders->OptionalHeader.Magic == 0x10b)
		return IMAGE_32BIT;
	else
	if (lpNtHeaders->OptionalHeader.Magic == 0x20b)
		return IMAGE_64BIT;

	return IMAGE_UNKNOWN;
}

unsigned int readImage (unsigned char* imagePath, char* buffer,
					int size) {

	FILE* pFile = 0;

	pFile = locateImage (imagePath);
	if (!pFile) {
		printf ("\n\rUnable to locate %s", imagePath);
		return 0;
	}

	fread (buffer, size, 1, pFile);
	fclose (pFile);
	return size;
}

void run (char* imagePath) {

	unsigned char buffer[512];
	imageType t = IMAGE_UNKNOWN;

	if ( readImage (imagePath, buffer, 512) == 0)
		return;

	t = determinType (buffer);
	printf ("\n\rImage '%s' type: ", imagePath);
	dispImageType (t);
}

int main(int argc, char* argv[]) {

	if (argc!=2) {
		printf ("\n\rMissing file name argument");
		return 0;
	}
	run (argv[1]);
}
```


----------



## Riverglen (Aug 29, 2006)

mt2002,

Wow. Thank you very much. Kind of above and beyond the call to take the time to write a little program for me and I really appreciate your having made the effort to do so. I will give it a try and let you know how I make out. It may be a day or so before I get to it though. I don't have any 64 bit stuff around here either, but it really isn't a problem. I am really just interested in a tool to help me sort the merely old stuff from the fossils.

And, regarding the remark by DoubleHelix, I do realize that a Windows program comes in a lot of pieces, but it is more than sufficient for my purposes to be able to characterize the root .exe module. Some of the stuff I have around here I wrote myself, using an old Quick C compiler. I'd rebuild it with a modern compiler but for the fact that the original programs used 3'rd party libraries that I don't have source for. Would it be nice to be able to link newly compiled 32 bit code with that old 16 bit stuff.


----------



## Riverglen (Aug 29, 2006)

Just wanted to close the loop. I finally got around to trying your little tool, and it works perfectly for my purposes. I did have to diddle around just a bit with the code to get it to compile with on old version of VisualC++. There was an inconsistency in the typing of the imagePath (unsigned char vs. char).

Thanks again for the help.


----------



## Squashman (Apr 4, 2003)

Years ago I wrote a Bash script that would mount our Netware Server Volumes to a Linux server and it would use the *FILE* command to search for executable files. The FILE command is basically used to identify what type of file it it looking at. It can tell you if it is a text file or even a compressed file. It isn't just for identifying executable files.

I found a Windows port of it and it does seem to show you if the file is a 32 bit executable.

```
C:\Program Files\GnuWin32\bin>file "C:\Program Files\Microsoft Office\OFFICE11\WINWORD.EXE"
C:\Program Files\Microsoft Office\OFFICE11\WINWORD.EXE; PE32 executable for MS Windows (GUI) Intel 80386 32-bit
```
I don't have any 64 bit files to test with.
I believe when it is a 16bit executable it says something to the sorts of MS-DOS or Win 3.X executable.

You can get the FILE command from here.
http://gnuwin32.sourceforge.net/


----------

