C, Programming

Edit PE file properties using C

Using MS Windows API you can edit PE file properties such as:
* File version
* Product version
* File Description
* Company name
* Internal name
* Copyright
* Original filename
* Product name

GetFileVersionInfoSize
Determines whether the operating system can retrieve version information for a specified file. If version information is available, GetFileVersionInfoSize returns the size, in bytes, of that information. – MSDN

GetFileVersionInfo
Retrieves version information for the specified file. – MSDN

VerQueryValue
Retrieves specified version information from the specified version-information resource. To retrieve the appropriate resource, before you call VerQueryValue, you must first call the GetFileVersionInfoSize function, and then the GetFileVersionInfo function. – MSDN

UpdateResource
Adds, deletes, or replaces a resource in a portable executable (PE) file. There are some restrictions on resource updates in files that contain Resource Configuration (RC Config) data: language-neutral (LN) files and language-specific resource (.mui) files. – MSDN

Update File/Product version

bool UpdateVersion(HANDLE resource, const WCHAR *filePath, const WCHAR *newVersion, bool updateFileVersion)
{
	unsigned char *data = 0;
	DWORD verSize = 0, handle = 0;
	VS_FIXEDFILEINFO *fixedFileInfo;
	unsigned int fixedFileInfoLen = 0;
	Translate *translate = 0;
	unsigned int translateLen = 0;
	unsigned int len = 0;
	DWORD newVersionInt[4];
 
	VerionStrToInt(newVersionInt, newVersion);
 
	if ((verSize = GetFileVersionInfoSizeW(filePath, &handle)) == 0)
	{
		return false;
	}
 
	data = (unsigned char *)malloc(verSize * sizeof(unsigned char));
	if (data == NULL)
	{
		return false;
	}
	SecureZeroMemory(data, verSize * sizeof(unsigned char));
 
	if (!GetFileVersionInfoW(filePath, 0, verSize, data))
	{
		SAFE_FREE(data);
		return false;
	}
 
	if (!VerQueryValueW(data, L"\\", (LPVOID*)&fixedFileInfo, &fixedFileInfoLen))
	{
		SAFE_FREE(data);
		return false;
	}
 
	if (fixedFileInfoLen < sizeof(&fixedFileInfo)) { SAFE_FREE(data); return false; } if (!VerQueryValueW(data, L"\\VarFileInfo\\Translation", (LPVOID*)&translate, &translateLen)) { SAFE_FREE(data); return false; } if (updateFileVersion) { fixedFileInfo->dwFileVersionMS = ((newVersionInt[0] & 0xFFFF) << 16) | (newVersionInt[1] & 0xFFFF); fixedFileInfo->dwFileVersionLS = ((newVersionInt[2] & 0xFFFF) << 16) | (newVersionInt[3] & 0xFFFF); } else { fixedFileInfo->dwProductVersionMS = ((newVersionInt[0] & 0xFFFF) << 16) | (newVersionInt[1] & 0xFFFF); fixedFileInfo->dwProductVersionLS = ((newVersionInt[2] & 0xFFFF) << 16) | (newVersionInt[3] & 0xFFFF); } if (!UpdateResourceW(resource, RT_VERSION, MAKEINTRESOURCEW(VS_VERSION_INFO), translate->Language, data, verSize))
		return false;
 
	SAFE_FREE(data);
	return true;
}

Update String values

bool UpdateStringVersion(HANDLE resource, const WCHAR *filePath, const WCHAR *field, const WCHAR *newValue)
{
	unsigned char *data = 0;
	//VS_FIXEDFILEINFO *fixedFileInfo;
	//unsigned int fixedFileInfoLen = 0;
	DWORD verSize = 0;
	DWORD handle = 0;
	Translate *translate;
	unsigned int translateLen = 0;
	WCHAR *value;
	unsigned int len = 0;
 
	if ((verSize = GetFileVersionInfoSizeW(filePath, &handle)) == 0)
	{
		return false;
	}
 
	data = (unsigned char *)malloc(verSize * sizeof(unsigned char));
	if (data == NULL)
	{
		return false;
	}
	SecureZeroMemory(data, verSize * sizeof(unsigned char));
 
	if (!GetFileVersionInfoW(filePath, 0, verSize, data))
	{
		SAFE_FREE(data);
		return false;
	}
 
	if (!VerQueryValueW(data, L"\\VarFileInfo\\Translation", (LPVOID*)&translate, &translateLen))
	{
		SAFE_FREE(data);
		return false;
	}
 
	if (!QueryInfo(&value, &len, field, data, translate->Language, translate->CodePage))
	{
		SAFE_FREE(data);
		return false;
	}
 
	SecureZeroMemory(value, len);
	wcsncpy_s(value, len, newValue, _TRUNCATE);
 
	if (!UpdateResourceW(resource, RT_VERSION, MAKEINTRESOURCEW(VS_VERSION_INFO), translate->Language, data, verSize))
		return false;
 
	SAFE_FREE(data);
	return true;
}

For full source code please visit MetaScrub project page.

git clone https://github.com/maldevel/MetaScrub