Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

688 lines
18 KiB

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include "stampinf.h"
DRIVER_VER_DATA dvdata;
BOOLEAN HaveDate = FALSE;
BOOLEAN HaveVersion = FALSE;
int _cdecl main (int argc, char **argv)
{
char *StampInfEnv;
//
// Zero out our main data structure
//
ZeroMemory (&dvdata, sizeof (DRIVER_VER_DATA));
//
// Process and validate the arguments
//
lstrcpy (dvdata.SectionName, "Version");
if (StampInfEnv = getenv("STAMPINF_DATE")) {
if (ValidateDate (StampInfEnv)) {
lstrcpy (dvdata.DateString, StampInfEnv);
HaveDate = TRUE;
}
else printf ("Date error\n");
}
if (StampInfEnv = getenv("STAMPINF_VERSION")) {
lstrcpyn (dvdata.VersionString, StampInfEnv, 20);
HaveVersion = TRUE;
}
if (!GetArgs (argc, argv)) {
DisplayHelp ();
return 1;
}
//
// Write the DriverVer key to the inf
//
if (!StampInf ()) {
printf ("Error writing to inf!\n");
return 1;
}
return 0;
}
BOOLEAN GetArgs (int argc, char **argv)
{
int args;
char *arg;
ARGTYPE argtype = ArgSwitch;
//
// Loop through the arguments, the filename is required
// but version and date are optional.
//
for (args = 1; args < argc; args++) {
arg = argv[args];
//
// switch based on the type of argument
// we are expecting.
//
switch (argtype) {
case ArgSwitch:
//
// better be a switch prefix
//
if (*arg != '-') return FALSE;
else arg++;
switch (toupper(*arg)) {
case 'F':
argtype = ArgFileName;
break;
case 'D':
argtype = ArgDate;
break;
case 'V':
argtype = ArgVersion;
break;
case 'S':
argtype = ArgSection;
break;
default:
printf ("Invalid argument %s\n", arg);
}
break;
case ArgFileName:
//
// See if the provided filename includes any
// path separators. If it doesn't prepend .\
// because the WritePrivateProfile api
// defaults to the Windows dir unless
// you specify a path.
//
if (strchr (arg, '\\') == NULL) {
lstrcpy (dvdata.InfName, ".\\");
}
//
// concatenate the actual file name
//
lstrcat (dvdata.InfName, arg);
argtype = ArgSwitch;
break;
case ArgDate:
//
// If the user specified a date, do some basic validation.
//
if (ValidateDate (arg)) {
lstrcpy (dvdata.DateString, arg);
HaveDate = TRUE;
}
else printf ("Date error\n");
argtype = ArgSwitch;
break;
case ArgVersion:
//
// If the user specified a version override, use it.
//
lstrcpyn (dvdata.VersionString, arg, 20);
argtype = ArgSwitch;
HaveVersion = TRUE;
break;
case ArgSection:
lstrcpyn (dvdata.SectionName, arg, 64);
argtype = ArgSwitch;
break;
}
}
if (!HaveDate) {
//
// Get the date in xx/yy/zzzz format.
//
GetDateFormat (LOCALE_SYSTEM_DEFAULT, 0, NULL, "MM'/'dd'/'yyyy", dvdata.DateString, 11);
}
if (!HaveVersion) {
//
// If the user didn't provide a version override, then open and read
// ntverp.h and figure out what the version stamp should be.
//
if (!ProcessNtVerP (dvdata.VersionString)) {
return FALSE;
}
}
//
// Must have a name.
//
return (dvdata.InfName[0] != '\0');
}
BOOLEAN ValidateDate (char *datestring)
{
ULONG Month, Day, Year;
if (lstrlen (datestring) != 10) return FALSE;
Month = atoi(&datestring[0]);
if (Month < 1 || Month > 12) return FALSE;
Day = atoi (&datestring[3]);
if (Day < 1 || Day > 31) return FALSE;
Year = atoi (&datestring[6]);
if (Year < 1980 || Year > 2099) return FALSE;
return TRUE;
}
ULONG GetLengthOfLine (WCHAR *Pos, WCHAR *LastChar)
{
ULONG Length=0;
if (Pos == NULL) return 0;
while ( (Pos < LastChar) && (*Pos != 0x00D) ) {
Pos++;
Length++;
}
if (Pos < LastChar) Length+=2;
return Length;
}
WCHAR *GetNextLine (WCHAR *CurPos, WCHAR *LastChar)
{
LastChar--;
for (;CurPos < LastChar;CurPos++) {
if ( (CurPos[0] == 0x00D) && (CurPos[1] == 0x00A) ) break;
}
return ( (&(CurPos[2]) <= LastChar) ? &(CurPos[2]) : NULL );
}
BOOLEAN DoesLineMatch (WCHAR *Target, WCHAR *Sample, WCHAR *LastChar)
{
USHORT LineLength = 0;
WCHAR *Pos = Sample;
WCHAR *buffer;
BOOLEAN result;
ULONG TargetLength;
if (Pos == NULL) return FALSE;
while ( (Pos <= LastChar) && (*Pos != 0x00D) ) {
LineLength++;
Pos++;
}
TargetLength = lstrlenW (Target);
if (TargetLength > LineLength) {
return FALSE;
}
return (BOOLEAN)(!memcmp (Target, Sample, TargetLength));
}
USHORT FindEntry (WCHAR *FileStart, WCHAR *FileEnd, WCHAR *SectionNameW, WCHAR **Entry)
{
WCHAR *FilePos=FileStart;
WCHAR FixedSectionNameW[64+2];
BOOLEAN FoundMatch = FALSE;
ULONG iter = 0;
wsprintfW (FixedSectionNameW, L"[%s]", SectionNameW);
for (FilePos = FileStart; FilePos; FilePos = GetNextLine (FilePos, FileEnd)) {
if (DoesLineMatch (FixedSectionNameW, FilePos, FileEnd)) {
FoundMatch = TRUE;
break;
}
}
if (FoundMatch) {
FoundMatch = FALSE;
while ( ((FilePos = GetNextLine (FilePos, FileEnd)) != NULL) && (*FilePos != L'[') ) {
if (DoesLineMatch (L"DriverVer", FilePos, FileEnd)) {
FoundMatch = TRUE;
break;
}
}
if (FoundMatch) {
*Entry = FilePos;
return FOUND_ENTRY;
}
if (FilePos) {
*Entry = FilePos;
return FOUND_SECTION;
}
}
*Entry = NULL;
return FOUND_NOTHING;
}
UINT UniWPPS (char *SectionName, char *Stamp, char *InfName)
{
WCHAR SectionNameW [64];
WCHAR *NextLinePtr;
WCHAR NewEntryW [64];
WCHAR StampW [32];
WCHAR InfNameW [MAX_PATH];
HANDLE hFile, hMapping;
WCHAR *MappedBuffer;
ULONG filesize;
WCHAR *LastChar;
WCHAR *Entry = NULL;
ULONG result;
ULONG StampLength;
ULONG numwritten;
ULONG deleted;
MultiByteToWideChar (CP_ACP,
MB_PRECOMPOSED,
SectionName,
(int)-1,
SectionNameW,
64);
MultiByteToWideChar (CP_ACP,
MB_PRECOMPOSED,
Stamp,
(int)-1,
StampW,
32);
MultiByteToWideChar (CP_ACP,
MB_PRECOMPOSED,
InfName,
(int)-1,
InfNameW,
MAX_PATH);
StampLength = lstrlenW (StampW);
hFile = CreateFile (InfName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
printf ("Create file failed!\n");
return 0;
}
filesize = GetFileSize (hFile, NULL);
hMapping = CreateFileMapping (hFile, NULL, PAGE_READWRITE, 0, filesize+128, NULL);
if (!hMapping) {
printf ("Map file failed!\n");
CloseHandle (hFile);
return 0;
}
MappedBuffer = MapViewOfFile (hMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0);
if (!MappedBuffer) {
printf ("MapView Failed!\n");
CloseHandle (hMapping);
CloseHandle (hFile);
return 0;
}
LastChar = (WCHAR *)((ULONG_PTR)MappedBuffer+filesize-sizeof(WCHAR));
result = FindEntry (MappedBuffer, LastChar, SectionNameW, &Entry);
wsprintfW (NewEntryW, L"DriverVer=%s\r\n",StampW);
StampLength = lstrlenW (NewEntryW);
switch (result) {
case FOUND_SECTION:
MoveMemory ((WCHAR *)((ULONG_PTR)Entry+(StampLength*sizeof(WCHAR))), Entry, (ULONG_PTR)LastChar-(ULONG_PTR)Entry+sizeof(WCHAR));
CopyMemory (Entry, NewEntryW, StampLength*sizeof(WCHAR));
UnmapViewOfFile (MappedBuffer);
CloseHandle (hMapping);
SetFilePointer (hFile, filesize+StampLength*sizeof(WCHAR), NULL, FILE_BEGIN);
SetEndOfFile (hFile);
break;
case FOUND_ENTRY:
deleted = GetLengthOfLine (Entry, LastChar);
deleted *=sizeof(WCHAR);
NextLinePtr = GetNextLine (Entry, LastChar);
MoveMemory ((WCHAR *)((ULONG_PTR)Entry+(StampLength*sizeof(WCHAR))), NextLinePtr, (ULONG_PTR)LastChar-(ULONG_PTR)NextLinePtr+sizeof(WCHAR));
CopyMemory (Entry, NewEntryW, StampLength*sizeof(WCHAR));
UnmapViewOfFile (MappedBuffer);
CloseHandle (hMapping);
SetFilePointer (hFile, filesize+StampLength*sizeof(WCHAR)-deleted, NULL, FILE_BEGIN);
SetEndOfFile (hFile);
break;
case FOUND_NOTHING:
UnmapViewOfFile (MappedBuffer);
CloseHandle (hMapping);
SetFilePointer (hFile, filesize, NULL, FILE_BEGIN);
SetEndOfFile (hFile);
break;
}
CloseHandle (hFile);
return 1;
}
BOOLEAN IsInfUnicode (VOID)
{
HANDLE hFile, hMapping;
char *MappedBuffer;
ULONG filesize;
BOOLEAN unicode = FALSE;
hFile = CreateFile (dvdata.InfName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
printf ("Create file failed!\n");
return FALSE;
}
hMapping = CreateFileMapping (hFile, NULL, PAGE_READONLY, 0, 0, NULL);
if (!hMapping) {
printf ("Map file failed!\n");
CloseHandle (hFile);
return FALSE;
}
MappedBuffer = MapViewOfFile (hMapping, FILE_MAP_READ, 0, 0, 0);
if (!MappedBuffer) {
printf ("MapView Failed!\n");
CloseHandle (hMapping);
CloseHandle (hFile);
return FALSE;
}
filesize = GetFileSize (hFile, NULL);
if (filesize < sizeof (WCHAR)) return 0;
if ( *((WCHAR *)MappedBuffer) == 0xFEFF ) {
unicode = TRUE;
}
if ( IsTextUnicode (MappedBuffer, filesize, NULL) ) {
unicode = TRUE;
}
UnmapViewOfFile (MappedBuffer);
CloseHandle (hMapping);
CloseHandle (hFile);
return unicode;
}
BOOLEAN StampInf (VOID)
{
char DateVerStamp[32];
wsprintf (DateVerStamp, "%s,%s",dvdata.DateString,dvdata.VersionString);
printf ("Stamping %s [%s] section with DriverVer=%s\n",dvdata.InfName, dvdata.SectionName, DateVerStamp);
//
// Let WritePrivateProfile do all of our work!
//
if (IsInfUnicode()) {
printf ("Unicode Inf Detected\n");
if (UniWPPS (dvdata.SectionName, DateVerStamp, dvdata.InfName) == 0) {
printf ("Error\n");
return FALSE;
}
}
else {
if (WritePrivateProfileString (dvdata.SectionName, "DriverVer", DateVerStamp, dvdata.InfName) == 0) {
printf ("Error\n");
return FALSE;
}
}
return TRUE;
}
VOID DisplayHelp (VOID)
{
printf ("\tUSAGE:\n");
printf ("\tstampinf -f filename [-s section] [-d xx/yy/zzzz] [-v w.x.y.z]\n");
}
DWORD NextInterestingCharacter (DWORD CurFilePos, DWORD Size, char *MappedBuffer)
{
char thischar;
DWORD NewPos;
//
// Find the next character that is not whitespace, EOL, or within a comment block.
// Return the offset into the buffer for that character, or Size if there is no
// such character.
//
while (CurFilePos < Size) {
thischar = MappedBuffer[CurFilePos];
if ( (thischar == 0x0A) || (thischar == 0x0D) || (thischar == ' ') ) {
CurFilePos++;
continue;
}
if (CurFilePos == Size-1)
break;
if ( (thischar == '/') && (MappedBuffer[CurFilePos+1] == '*') ) {
//
// Skip past the comment char's and search for the end of the comment block
//
NewPos = CurFilePos+2;
while (NewPos < (Size-1)) {
if ( (MappedBuffer[NewPos] == '*') && (MappedBuffer[NewPos+1] == '/') ) {
CurFilePos = NewPos+1;
break;
}
NewPos++;
}
}
else if ( (thischar == '/') && (MappedBuffer[CurFilePos+1] == '/') ) {
// Search for newline or EOF
CurFilePos += 2;
while (CurFilePos < (Size-1)) {
if ( (MappedBuffer[CurFilePos] == 0x0A) || (MappedBuffer[CurFilePos] == 0x0D)) {
break;
}
CurFilePos++;
}
}
else {
break;
}
CurFilePos++;
}
return CurFilePos;
}
DWORD FindLengthOfInterestingCharacters (DWORD CurFilePos, DWORD Size, char *MappedBuffer)
{
DWORD Pos = CurFilePos;
char thischar;
//
// Find the length of a string. Return the length.
//
while (Pos < Size) {
thischar = MappedBuffer[Pos];
if ( (thischar == 0x0A) || (thischar == 0x0D) || (thischar == ' ') || (thischar == '/') ) {
return (Pos-CurFilePos);
}
Pos++;
}
printf ("How did we get here?\n");
return 0;
}
BOOLEAN ProcessNtVerP (char *VersionString)
{
HANDLE hFile, hMapping;
char *MappedBuffer, *location;
DWORD pos;
DWORD qfelen,buildlen,majorverlen,minorverlen;
char qfe[5]={'0','0','0','0',0};
char build[5]={'0','0','0','0',0};
char majorversion[5]={'0','0','0','0',0};
char minorversion[5]={'0','0','0','0',0};
DWORD filesize;
char *p;
TCHAR ntroot[MAX_PATH];
if ( GetEnvironmentVariable ("_NTDRIVE", ntroot, 3) == 0 ) {
printf ("Unable to evaluate _NTDRIVE!\n");
return FALSE;
}
if ( GetEnvironmentVariable ("_NTROOT", &(ntroot[2]), MAX_PATH-2) == 0 ) {
printf ("Unable to evaluate _NTROOT!\n");
return FALSE;
}
lstrcat (ntroot, "\\public\\sdk\\inc\\ntverp.h");
printf ("Using version information from %s\n",ntroot);
//
// Create a memory mapped image of ntverp.h
//
hFile = CreateFile (ntroot, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
printf ("Create file failed!\n");
return FALSE;
}
filesize = GetFileSize (hFile, NULL);
hMapping = CreateFileMapping (hFile, NULL, PAGE_READONLY, 0, 0, NULL);
if (!hMapping) {
printf ("Map file failed!\n");
CloseHandle (hFile);
return FALSE;
}
MappedBuffer = MapViewOfFile (hMapping, FILE_MAP_READ, 0, 0, 0);
if (!MappedBuffer) {
printf ("MapView Failed!\n");
CloseHandle (hMapping);
CloseHandle (hFile);
return FALSE;
}
//
// The version is made up of a.b.c.d where a.b is the Product Version.
// c is the Build and d is the QFE level. (e.g. 5.0.1922.1)
//
location = strstr (MappedBuffer, "#define VER_PRODUCTMAJORVERSION ");
pos = NextInterestingCharacter ((DWORD)(location-MappedBuffer+32), filesize, MappedBuffer);
majorverlen = FindLengthOfInterestingCharacters (pos, filesize, MappedBuffer);
lstrcpyn (majorversion, &(MappedBuffer[pos]), majorverlen+1);
location = strstr (MappedBuffer, "#define VER_PRODUCTMINORVERSION ");
pos = NextInterestingCharacter ((DWORD)(location-MappedBuffer+32), filesize, MappedBuffer);
minorverlen = FindLengthOfInterestingCharacters (pos, filesize, MappedBuffer);
lstrcpyn (minorversion, &(MappedBuffer[pos]), minorverlen+1);
location = strstr (MappedBuffer, "#define VER_PRODUCTBUILD ");
pos = NextInterestingCharacter ((DWORD)(location-MappedBuffer+25), filesize, MappedBuffer);
buildlen = FindLengthOfInterestingCharacters (pos, filesize, MappedBuffer);
lstrcpyn (build, &(MappedBuffer[pos]), buildlen+1);
location = strstr (MappedBuffer, "#define VER_PRODUCTBUILD_QFE ");
pos = NextInterestingCharacter ((DWORD)(location-MappedBuffer+29), filesize, MappedBuffer);
qfelen = FindLengthOfInterestingCharacters (pos, filesize, MappedBuffer);
lstrcpyn (qfe, &(MappedBuffer[pos]), qfelen+1);
wsprintf (VersionString, "%s.%s.%s.%s",majorversion, minorversion, build, qfe);
UnmapViewOfFile (MappedBuffer);
CloseHandle (hMapping);
CloseHandle (hFile);
return TRUE;
}