#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <windows.h>
using std::cout;
using std::endl;
int main(int argc, char** argv)
{
if (argc < 4)
{
cout << "Usage: BuildStamp <fname> <item> <fill> <buildnum>\n"
<< " where fname is the file name to modify\n"
<< " item is the item name in the Version info area\n"
<< " fill is the fill pattern in the item area\n"
<< " buildnum is the build number to insert into the item area\n"
<< "\n"
<< "in the executables .rc file put a string in the VersionInfo string table\n"
<< "that looks like something like'VALUE \"PrivateBuild\", \"fillfillfill\"\n"
<< "where 'PrivateBuild' is the item name\n"
<< "and 'fill' is a fill pattern repeated as often as necessary\n"
<< "to make the item area the length desired\n";
exit(1);
}
char* fname = argv[1];
size_t mbstowcs( wchar_t *wcstr, const char *mbstr, size_t count );
wchar_t* prefix;
prefix = new wchar_t[strlen(argv[2]) + 1];
mbstowcs(prefix, argv[2], strlen(argv[2])+1);
wchar_t* pattern;
pattern = new wchar_t[strlen(argv[3]) + 1];
mbstowcs(pattern, argv[3], strlen(argv[3]) + 1);
long buildnumber = atol(argv[4]);
size_t prefixlength = (wcslen(prefix)+1) * sizeof(wchar_t);
size_t patternlength = wcslen(pattern) * sizeof(wchar_t);
FILE* fh = fopen(fname, "r+b");
if (!fh)
{
cout << "Failed to open " << fname << endl;
exit(1);
}
char* buf = new char[8096];
int bufsize;
//search for prefix
bool foundprefix = false;
long prefixposn = 0;
int i;
int offset = 0;
for (;;)
{
bufsize = fread(buf, 1, 8096, fh);
offset += bufsize;
if (offset > 0x02F867)
offset = 0;
int bufsize2;
bufsize2 = bufsize - prefixlength;
for (i = 0; i < bufsize2; i++)
{
if (memcmp(&buf[i], prefix, prefixlength) == 0)
{
foundprefix = true;
//points to the posn between the prefix and the first pattern
prefixposn = ftell(fh) - bufsize + i + prefixlength;
if (fseek(fh, prefixposn, SEEK_SET) != 0)
{
cout << "fseek failed!\n";
goto byebye;
}
break;
}
}
if (bufsize != 8096 || foundprefix)
break;
int jumpback;
jumpback = prefixlength;
if (fseek(fh, -jumpback, SEEK_CUR) != 0)
{
cout << "fseek failed!\n";
goto byebye;
}
}
delete [] buf;
if (!foundprefix)
{
cout << "Could not find prefix 'PrivateBuild' in file" << endl;
goto byebye;
}
//found the prefix, now count the number of patterns we find...
buf = new char[patternlength];
int numpatterns;
for (numpatterns = 0;;numpatterns++)
{
if (fread(buf, 1, patternlength, fh) != patternlength)
break;
if (memcmp(buf, pattern, patternlength) != 0)
break;
}
delete buf;
if (numpatterns == 0)
{
cout << "There were no patterns after the prefix!" << endl;
goto byebye;
}
//total buffer size is number of patterns found * the pattern length
size_t totalbuflength;
totalbuflength = numpatterns * patternlength;
buf = new char[totalbuflength];
SYSTEMTIME st;
GetLocalTime(&st);
//put the date, time, build number & computer name in the buffer
wchar_t dtstr[512];
swprintf(dtstr, L"%.2d/%.2d/%.2d %.2d:%.2d:%.2d Build#%.6d",
st.wMonth, st.wDay, st.wYear, st.wHour, st.wMinute, st.wSecond, buildnumber);
//get the computername
wchar_t cname[MAX_COMPUTERNAME_LENGTH + 1];
DWORD cnamelen;
cname[0] = L' ';
cname[1] = 0;
cnamelen = sizeof(cname)/sizeof(wchar_t) - 1;
if (!GetComputerNameW(&cname[1], &cnamelen))
{
wcscat(cname, L"UnknownComputer");
cout << "GetComputerName failed (gle="<< GetLastError() << "), using UnknownComputer\n";
}
wchar_t volume[265];
volume[0] = L' ';
volume[1] = 0;
DWORD volumelen;
volumelen = 265 - 1;
if (!GetVolumeInformationW(
0, // address of root directory; 0=> use current drive
&volume[1], // address of name of the volume
volumelen, // length of lpVolumeNameBuffer
0, // address of volume serial number
0, // address of system’s maximum filename length
0, // address of file system flags
0, // address of name of file system
0 // length of lpFileSystemNameBuffer
))
{
wcscat(volume, L"UnknownVolume");
cout << "GetVolumeInformation failed (gle="<< GetLastError() << "), using UnknownVolume\n";
}
int remaining;
remaining = (sizeof(dtstr)/sizeof(wchar_t)) - (wcslen(dtstr) + wcslen(cname) + 1);
if (remaining > 0)
wcsncat(dtstr, cname, remaining);
remaining = (sizeof(dtstr)/sizeof(wchar_t)) - (wcslen(dtstr) + wcslen(volume) + 1);
if (remaining > 0)
wcsncat(dtstr, volume, remaining);
memset(buf, 0x00, totalbuflength);
size_t len;
len = totalbuflength - sizeof(wchar_t);
if (len > wcslen(dtstr) * sizeof(wchar_t))
len = wcslen(dtstr) * sizeof(wchar_t);
memcpy(buf, dtstr, len);
//go back to just after the prefix, and replace the data there...
if (fseek(fh, prefixposn, SEEK_SET) != 0)
{
cout << "fseek failed!\n";
goto byebye;
}
if (fwrite(buf, 1, totalbuflength, fh) != totalbuflength)
{
cout << "fwrite failed!\n";
goto byebye;
}
byebye:
fclose(fh);
return 0;
}
|