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.
1349 lines
31 KiB
1349 lines
31 KiB
/*++
|
|
Driver Match will parse a set of files, remember the list
|
|
of drivers in each file, and print the drivers common to
|
|
all the XML files.
|
|
--*/
|
|
|
|
|
|
#include <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
#include <windows.h>
|
|
#include <stdio.h>
|
|
#include <conio.h>
|
|
#include <stdlib.h>
|
|
#include <TCHAR.h>
|
|
|
|
#include <diamondd.h>
|
|
#include <lzexpand.h>
|
|
#include <fcntl.h>
|
|
|
|
|
|
#define OSVERSION_TAG L"<OSVER>"
|
|
#define DRIVER_TAG L"<DRIVER>"
|
|
#define FILENAME_TAG L"<FILENAME>"
|
|
#define VERSION_TAG L"<VERSION>"
|
|
#define MANUFACT_TAG L"<MANUFACTURER>"
|
|
#define MICROSOFT_MANUFACTURER L"Microsoft Corporation"
|
|
|
|
|
|
|
|
//
|
|
// Info about a specific driver.
|
|
//
|
|
typedef struct _FILE_ENTRY {
|
|
|
|
struct _FILE_ENTRY *Next;
|
|
|
|
PTSTR FileName;
|
|
struct _VERSION_ENTRY *VersionList;
|
|
//PTSTR FileVersion;
|
|
ULONG RefCount;
|
|
|
|
} FILE_ENTRY, *PFILE_ENTRY;
|
|
|
|
typedef struct _VERSION_ENTRY {
|
|
struct _VERSION_ENTRY *Next;
|
|
PFILE_ENTRY FileEntry;
|
|
PTSTR FileVersion;
|
|
ULONG RefCount;
|
|
} VERSION_ENTRY, *PVERSION_ENTRY;
|
|
|
|
|
|
PFILE_ENTRY MasterFileList = NULL;
|
|
ULONG FilesProcessed = 0;
|
|
BOOLEAN ExcludeMicrosoftDrivers = FALSE;
|
|
|
|
|
|
|
|
//
|
|
// Diamond stuff so we can crack .CAB files.
|
|
//
|
|
HFDI FdiContext;
|
|
DWORD LastError;
|
|
ERF FdiError;
|
|
PVOID DecompBuffer = NULL;
|
|
ULONG SizeOfFileInDecompressBuffer = 0;
|
|
ULONG DecompressBufferSize;
|
|
|
|
//
|
|
// This is the value we return to diamond when it asks us to create
|
|
// the target file.
|
|
//
|
|
#define DECOMP_MAGIC_HANDLE 0x87654
|
|
|
|
|
|
|
|
//
|
|
// Private malloc/free routines so we can track memory
|
|
// if we ever want to.
|
|
//
|
|
VOID *MyMalloc( size_t Size )
|
|
{
|
|
PVOID ReturnPtr = NULL;
|
|
|
|
ReturnPtr = malloc(Size);
|
|
if( ReturnPtr ) {
|
|
RtlZeroMemory( ReturnPtr, Size );
|
|
}
|
|
|
|
return ReturnPtr;
|
|
}
|
|
|
|
VOID MyFree( PVOID Ptr )
|
|
{
|
|
free( Ptr );
|
|
}
|
|
|
|
PSTR
|
|
UnicodeStringToAnsiString(
|
|
PWSTR StringW
|
|
)
|
|
{
|
|
UNICODE_STRING UStr;
|
|
ANSI_STRING AStr;
|
|
ULONG AnsiLength,Index;
|
|
|
|
RtlInitUnicodeString(&UStr, StringW);
|
|
|
|
AnsiLength = RtlUnicodeStringToAnsiSize(&UStr);
|
|
|
|
AStr.MaximumLength = (USHORT)AnsiLength;
|
|
AStr.Length = (USHORT) AnsiLength - 1;
|
|
|
|
AStr.Buffer = MyMalloc(AStr.MaximumLength);
|
|
|
|
if (!AStr.Buffer) {
|
|
return(NULL);
|
|
}
|
|
|
|
RtlUnicodeToMultiByteN( AStr.Buffer,
|
|
AStr.Length,
|
|
&Index,
|
|
UStr.Buffer,
|
|
UStr.Length
|
|
);
|
|
|
|
return(AStr.Buffer);
|
|
}
|
|
|
|
|
|
PVOID
|
|
DIAMONDAPI
|
|
SpdFdiAlloc(
|
|
IN ULONG NumberOfBytes
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Callback used by FDICopy to allocate memory.
|
|
|
|
Arguments:
|
|
|
|
NumberOfBytes - supplies desired size of block.
|
|
|
|
Return Value:
|
|
|
|
Returns pointer to a block of memory or NULL
|
|
if memory cannot be allocated.
|
|
|
|
--*/
|
|
|
|
{
|
|
return(MyMalloc(NumberOfBytes));
|
|
}
|
|
|
|
|
|
VOID
|
|
DIAMONDAPI
|
|
SpdFdiFree(
|
|
IN PVOID Block
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Callback used by FDICopy to free a memory block.
|
|
The block must have been allocated with SpdFdiAlloc().
|
|
|
|
Arguments:
|
|
|
|
Block - supplies pointer to block of memory to be freed.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
MyFree(Block);
|
|
}
|
|
|
|
|
|
INT_PTR
|
|
DIAMONDAPI
|
|
SpdFdiOpen(
|
|
IN PSTR FileName,
|
|
IN int oflag,
|
|
IN int pmode
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Callback used by FDICopy to open files.
|
|
|
|
This routine is capable only of opening existing files.
|
|
|
|
When making changes here, also take note of other places
|
|
that open the file directly (search for SpdFdiOpen)
|
|
|
|
Arguments:
|
|
|
|
FileName - supplies name of file to be opened.
|
|
|
|
oflag - supplies flags for open.
|
|
|
|
pmode - supplies additional flags for open.
|
|
|
|
Return Value:
|
|
|
|
Handle to open file or -1 if error occurs.
|
|
|
|
--*/
|
|
|
|
{
|
|
HANDLE h;
|
|
|
|
UNREFERENCED_PARAMETER(pmode);
|
|
|
|
if(oflag & (_O_WRONLY | _O_RDWR | _O_APPEND | _O_CREAT | _O_TRUNC | _O_EXCL)) {
|
|
LastError = ERROR_INVALID_PARAMETER;
|
|
return(-1);
|
|
}
|
|
|
|
h = CreateFileA(FileName,
|
|
GENERIC_READ,
|
|
FILE_SHARE_READ,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
0,
|
|
NULL);
|
|
if(h == INVALID_HANDLE_VALUE) {
|
|
LastError = GetLastError();
|
|
return(-1);
|
|
}
|
|
|
|
return (INT_PTR)h;
|
|
}
|
|
|
|
UINT
|
|
DIAMONDAPI
|
|
SpdFdiRead(
|
|
IN INT_PTR Handle,
|
|
OUT PVOID pv,
|
|
IN UINT ByteCount
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Callback used by FDICopy to read from a file.
|
|
|
|
Arguments:
|
|
|
|
Handle - supplies handle to open file to be read from.
|
|
|
|
pv - supplies pointer to buffer to receive bytes we read.
|
|
|
|
ByteCount - supplies number of bytes to read.
|
|
|
|
Return Value:
|
|
|
|
Number of bytes read or -1 if an error occurs.
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD d;
|
|
HANDLE hFile = (HANDLE)Handle;
|
|
DWORD bytes;
|
|
UINT rc;
|
|
|
|
if (Handle == DECOMP_MAGIC_HANDLE) {
|
|
return(-1);
|
|
}
|
|
|
|
if(ReadFile(hFile,pv,(DWORD)ByteCount,&bytes,NULL)) {
|
|
rc = (UINT)bytes;
|
|
} else {
|
|
d = GetLastError();
|
|
rc = (UINT)(-1);
|
|
|
|
LastError = d;
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
|
|
UINT
|
|
DIAMONDAPI
|
|
SpdFdiWrite(
|
|
IN INT_PTR Handle,
|
|
IN PVOID pv,
|
|
IN UINT ByteCount
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Callback used by FDICopy to write to a file.
|
|
|
|
Arguments:
|
|
|
|
Handle - supplies handle to open file to be written to.
|
|
|
|
pv - supplies pointer to buffer containing bytes to write.
|
|
|
|
ByteCount - supplies number of bytes to write.
|
|
|
|
Return Value:
|
|
|
|
Number of bytes written (ByteCount) or -1 if an error occurs.
|
|
|
|
--*/
|
|
|
|
{
|
|
if (Handle != DECOMP_MAGIC_HANDLE) {
|
|
return(-1);
|
|
}
|
|
|
|
//
|
|
// Check for overflow.
|
|
//
|
|
if(SizeOfFileInDecompressBuffer+ByteCount > DecompressBufferSize) {
|
|
return((UINT)(-1));
|
|
}
|
|
|
|
RtlCopyMemory(
|
|
(PCHAR)DecompBuffer + SizeOfFileInDecompressBuffer,
|
|
pv,
|
|
ByteCount
|
|
);
|
|
|
|
SizeOfFileInDecompressBuffer += ByteCount;
|
|
return(ByteCount);
|
|
|
|
}
|
|
|
|
|
|
int
|
|
DIAMONDAPI
|
|
SpdFdiClose(
|
|
IN INT_PTR Handle
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Callback used by FDICopy to close files.
|
|
|
|
Arguments:
|
|
|
|
Handle - handle of file to close.
|
|
|
|
Return Value:
|
|
|
|
0 (success).
|
|
|
|
--*/
|
|
|
|
{
|
|
BOOL success = FALSE;
|
|
|
|
if (Handle != DECOMP_MAGIC_HANDLE) {
|
|
CloseHandle((HANDLE)Handle);
|
|
}
|
|
|
|
//
|
|
// Always act like we succeeded.
|
|
//
|
|
return 0;
|
|
}
|
|
|
|
|
|
long
|
|
DIAMONDAPI
|
|
SpdFdiSeek(
|
|
IN INT_PTR Handle,
|
|
IN long Distance,
|
|
IN int SeekType
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Callback used by FDICopy to seek files.
|
|
|
|
Arguments:
|
|
|
|
Handle - handle of file to close.
|
|
|
|
Distance - supplies distance to seek. Interpretation of this
|
|
parameter depends on the value of SeekType.
|
|
|
|
SeekType - supplies a value indicating how Distance is to be
|
|
interpreted; one of SEEK_SET, SEEK_CUR, SEEK_END.
|
|
|
|
Return Value:
|
|
|
|
New file offset or -1 if an error occurs.
|
|
|
|
--*/
|
|
|
|
{
|
|
LONG rc;
|
|
DWORD d;
|
|
HANDLE hFile = (HANDLE)Handle;
|
|
DWORD pos_low;
|
|
DWORD method;
|
|
|
|
if (Handle == DECOMP_MAGIC_HANDLE) {
|
|
return(-1);
|
|
}
|
|
|
|
switch(SeekType) {
|
|
case SEEK_SET:
|
|
method = FILE_BEGIN;
|
|
break;
|
|
|
|
case SEEK_CUR:
|
|
method = FILE_CURRENT;
|
|
break;
|
|
|
|
case SEEK_END:
|
|
method = FILE_END;
|
|
break;
|
|
|
|
default:
|
|
return -1;
|
|
}
|
|
|
|
pos_low = SetFilePointer(hFile,(DWORD)Distance,NULL,method);
|
|
if(pos_low == INVALID_SET_FILE_POINTER) {
|
|
d = GetLastError();
|
|
rc = -1L;
|
|
|
|
LastError = d;
|
|
} else {
|
|
rc = (long)pos_low;
|
|
}
|
|
|
|
return(rc);
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
DiamondInitialize(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Per-thread initialization routine for Diamond.
|
|
Called once per thread.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
Boolean result indicating success or failure.
|
|
Failure can be assumed to be out of memory.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
BOOL retval = FALSE;
|
|
|
|
try {
|
|
|
|
//
|
|
// Initialize a diamond context.
|
|
//
|
|
FdiContext = FDICreate(
|
|
SpdFdiAlloc,
|
|
SpdFdiFree,
|
|
SpdFdiOpen,
|
|
SpdFdiRead,
|
|
SpdFdiWrite,
|
|
SpdFdiClose,
|
|
SpdFdiSeek,
|
|
cpuUNKNOWN,
|
|
&FdiError
|
|
);
|
|
|
|
if(FdiContext) {
|
|
retval = TRUE;
|
|
}
|
|
|
|
} except(EXCEPTION_EXECUTE_HANDLER) {
|
|
retval = FALSE;
|
|
}
|
|
|
|
return(retval);
|
|
}
|
|
|
|
|
|
VOID
|
|
DiamondTerminate(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Per-thread termination routine for Diamond.
|
|
Called internally.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
Boolean result indicating success or failure.
|
|
Failure can be assumed to be out of memory.
|
|
|
|
--*/
|
|
{
|
|
FDIDestroy(FdiContext);
|
|
FdiContext = NULL;
|
|
}
|
|
|
|
INT_PTR
|
|
DIAMONDAPI
|
|
NotifyFunction(
|
|
FDINOTIFICATIONTYPE fdint,
|
|
PFDINOTIFICATION pfdin)
|
|
{
|
|
switch(fdint) {
|
|
case fdintCOPY_FILE:
|
|
if (_strcmpi(pfdin->psz1,"sysdata.xml") == 0) {
|
|
DecompressBufferSize = pfdin->cb+2;
|
|
DecompBuffer = MyMalloc(DecompressBufferSize);
|
|
if (!DecompBuffer) {
|
|
return(-1);
|
|
}
|
|
SizeOfFileInDecompressBuffer = 0;
|
|
return(DECOMP_MAGIC_HANDLE);
|
|
}
|
|
return(0);
|
|
break;
|
|
|
|
case fdintCLOSE_FILE_INFO:
|
|
if (pfdin->hf == DECOMP_MAGIC_HANDLE) {
|
|
return(TRUE);
|
|
}
|
|
return(FALSE);
|
|
break;
|
|
|
|
default:
|
|
return(0);
|
|
}
|
|
|
|
return(0);
|
|
}
|
|
|
|
BOOL
|
|
DiamondExtractFileIntoBuffer(
|
|
PTSTR DirectoryName,
|
|
PTSTR FileName,
|
|
PVOID *Buffer,
|
|
PDWORD FileSize
|
|
)
|
|
{
|
|
HANDLE h;
|
|
PSTR FileNameA;
|
|
PSTR DirectoryNameA;
|
|
CHAR File[MAX_PATH];
|
|
ULONG i;
|
|
|
|
#ifdef UNICODE
|
|
FileNameA = UnicodeStringToAnsiString(FileName);
|
|
DirectoryNameA = UnicodeStringToAnsiString(DirectoryName);
|
|
#else
|
|
DirectoryNameA = DirectoryName;
|
|
FileNameA = FileName;
|
|
#endif
|
|
|
|
strcpy(File, DirectoryNameA);
|
|
i = strlen(File);
|
|
if (File[i-1] != '\\') {
|
|
File[i] = '\\';
|
|
File[i+1] = '\0';
|
|
}
|
|
strcat(File, FileNameA);
|
|
|
|
h = (HANDLE)SpdFdiOpen(File, 0, 0);
|
|
|
|
if (h == INVALID_HANDLE_VALUE) {
|
|
return(FALSE);
|
|
}
|
|
|
|
SpdFdiSeek( (INT_PTR)h, 0, SEEK_SET );
|
|
|
|
DecompBuffer = NULL;
|
|
LastError = ERROR_SUCCESS;
|
|
#if 0
|
|
GetCurrentDirectoryA(MAX_PATH,Dir);
|
|
i = strlen(Dir);
|
|
Dir[i] = '\\';
|
|
Dir[i+1] = '\0';
|
|
#endif
|
|
|
|
if (!FDICopy(FdiContext,
|
|
FileNameA,
|
|
DirectoryNameA,// Dir,//FileNameA,
|
|
0,
|
|
NotifyFunction,
|
|
NULL,
|
|
Buffer)) {
|
|
return(FALSE);
|
|
}
|
|
|
|
SpdFdiClose((INT_PTR)h);
|
|
|
|
#ifdef UNICODE
|
|
MyFree(FileNameA);
|
|
MyFree(DirectoryNameA);
|
|
#endif
|
|
|
|
if (LastError == ERROR_SUCCESS) {
|
|
if (DecompBuffer) {
|
|
*Buffer = DecompBuffer;
|
|
*FileSize = DecompressBufferSize;
|
|
return(TRUE);
|
|
} else {
|
|
return(FALSE);
|
|
}
|
|
} else {
|
|
return(FALSE);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
void
|
|
Usage( char *AppName )
|
|
{
|
|
if (AppName == NULL) {
|
|
return;
|
|
}
|
|
printf( "\n\n" );
|
|
printf( "Usage: %s [-m] <filename>\n", AppName );
|
|
printf( " Searchs the given XML files for all the drivers and\n" );
|
|
printf( " collates a list of drivers common to all the files.\n" );
|
|
printf( "\n" );
|
|
printf( " -m (OPTIONAL) Exclude drivers manufactured by Microsoft Corporation.\n" );
|
|
printf( "\n" );
|
|
printf( " <filename> May contain wildcards. Search this file(s) for drivers.\n" );
|
|
printf( "\n" );
|
|
printf( " EXAMPLE:\n" );
|
|
printf( " %s -m sysdata*.xml\n", AppName );
|
|
printf( "\n" );
|
|
printf( " This would examine every file which matches the pattern 'sysdata*.xml'\n" );
|
|
printf( " and build a list of non-Microsoft drivers which are common to all the files.\n" );
|
|
printf( "\n\n" );
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
AddDriverEntry(
|
|
PWSTR DriverName,
|
|
PWSTR DriverVersion
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Insert a driver entry into the MasterFileList. Note that it should be inserted in
|
|
ascending order with respect to the FileName.
|
|
|
|
Arguments:
|
|
|
|
DriverName Name of the specified driver.
|
|
|
|
DriverVersion String containing the version of the specified driver.
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
PFILE_ENTRY LastEntry = NULL;
|
|
PFILE_ENTRY ThisEntry = NULL;
|
|
PVERSION_ENTRY ThisVEntry = NULL;
|
|
PVERSION_ENTRY LastVEntry = NULL;
|
|
|
|
|
|
|
|
if( DriverName == NULL ) {
|
|
//printf( "AddDriverEntry: Bad incoming parameter\n" );
|
|
return(FALSE);
|
|
}
|
|
|
|
//printf( "AddDriverEntry Enter: Adding filename %S\n", DriverName );
|
|
|
|
if( MasterFileList == NULL ) {
|
|
//
|
|
// First entry for the machine.
|
|
//
|
|
//printf( " Adding the very first entry.\n" );
|
|
MasterFileList = MyMalloc(sizeof(FILE_ENTRY));
|
|
if (!MasterFileList) {
|
|
return(FALSE);
|
|
}
|
|
|
|
ThisVEntry = MyMalloc(sizeof(VERSION_ENTRY));
|
|
if (!ThisVEntry) {
|
|
MyFree(MasterFileList);
|
|
MasterFileList = NULL;
|
|
return(FALSE);
|
|
}
|
|
|
|
MasterFileList->FileName = DriverName;
|
|
MasterFileList->VersionList = ThisVEntry;
|
|
MasterFileList->Next = NULL;
|
|
MasterFileList->RefCount = 1;
|
|
ThisVEntry->FileEntry = MasterFileList;
|
|
ThisVEntry->RefCount = 1;
|
|
ThisVEntry->FileVersion = DriverVersion;
|
|
ThisVEntry->Next = NULL;
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
LastEntry = MasterFileList;
|
|
ThisEntry = MasterFileList;
|
|
|
|
//
|
|
// Find a spot to add this driver into our list.
|
|
//
|
|
while( ThisEntry &&
|
|
(_wcsicmp(ThisEntry->FileName, DriverName) < 0)) {
|
|
//printf( " Checking against filename %S\n", ThisEntry->FileName );
|
|
LastEntry = ThisEntry;
|
|
ThisEntry = ThisEntry->Next;
|
|
}
|
|
|
|
|
|
//
|
|
// Handle all the cases that would make use break out of the above loop.
|
|
//
|
|
if( ThisEntry == NULL ) {
|
|
//
|
|
// insert at the tail.
|
|
//
|
|
//printf( " Inserting at the tail of our list.\n" );
|
|
LastEntry->Next = MyMalloc(sizeof(FILE_ENTRY));
|
|
if (!LastEntry->Next) {
|
|
return(FALSE);
|
|
}
|
|
LastEntry->Next->VersionList = MyMalloc(sizeof(VERSION_ENTRY));
|
|
if (!LastEntry->Next->VersionList) {
|
|
MyFree(LastEntry->Next);
|
|
LastEntry->Next = NULL;
|
|
return(FALSE);
|
|
}
|
|
|
|
ThisEntry = LastEntry->Next;
|
|
ThisEntry->FileName = DriverName;
|
|
ThisEntry->RefCount = 1;
|
|
ThisEntry->Next = NULL;
|
|
ThisEntry->VersionList->FileVersion = DriverVersion;
|
|
ThisEntry->VersionList->FileEntry = ThisEntry;
|
|
ThisEntry->VersionList->Next = NULL;
|
|
ThisEntry->VersionList->RefCount = 1;
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
if( !_wcsicmp(ThisEntry->FileName, DriverName)) {
|
|
//printf( " Found a duplicate drivername!\n" );
|
|
|
|
ThisEntry->RefCount++;
|
|
|
|
LastVEntry = ThisEntry->VersionList;
|
|
ThisVEntry = ThisEntry->VersionList;
|
|
|
|
//
|
|
// Find a spot to add this driver into our list.
|
|
//
|
|
while( ThisVEntry &&
|
|
(_wcsicmp(ThisVEntry->FileVersion, DriverVersion) < 0)) {
|
|
//printf( " Checking against version %S\n", ThisVEntry->FileVersion );
|
|
LastVEntry = ThisVEntry;
|
|
ThisVEntry = ThisVEntry->Next;
|
|
}
|
|
|
|
if (!ThisVEntry) {
|
|
//printf( " Inserting version at the tail of our list.\n" );
|
|
LastVEntry->Next = MyMalloc(sizeof(VERSION_ENTRY));
|
|
if (!LastVEntry->Next) {
|
|
MyFree(LastVEntry->Next);
|
|
LastVEntry->Next = NULL;
|
|
return(FALSE);
|
|
}
|
|
|
|
ThisVEntry = LastVEntry->Next;
|
|
ThisVEntry->FileVersion = DriverVersion;
|
|
ThisVEntry->FileEntry = ThisEntry;
|
|
ThisVEntry->Next = NULL;
|
|
ThisVEntry->RefCount = 1;
|
|
return(TRUE);
|
|
}
|
|
|
|
if (!_wcsicmp(ThisVEntry->FileVersion, DriverVersion)) {
|
|
ThisVEntry->RefCount++;
|
|
return(TRUE);
|
|
}
|
|
|
|
if (LastVEntry == ThisVEntry) {
|
|
//
|
|
// Put it at the very head of the list
|
|
//
|
|
//printf( " Inserting version at the head of our list.\n" );
|
|
ThisVEntry = ThisEntry->VersionList;
|
|
ThisEntry->VersionList = MyMalloc(sizeof(VERSION_ENTRY));
|
|
if (!ThisEntry->VersionList) {
|
|
ThisEntry->VersionList = ThisVEntry;
|
|
return(FALSE);
|
|
}
|
|
|
|
ThisEntry->VersionList->FileVersion = DriverVersion;
|
|
ThisEntry->VersionList->FileEntry = ThisEntry;
|
|
ThisEntry->VersionList->Next = LastVEntry;
|
|
ThisEntry->VersionList->RefCount = 1;
|
|
return(TRUE);
|
|
}
|
|
|
|
//
|
|
// insert between LastEntry and ThisEntry
|
|
//
|
|
LastVEntry->Next = MyMalloc(sizeof(VERSION_ENTRY));
|
|
if (!LastVEntry->Next) {
|
|
LastVEntry->Next = ThisVEntry;
|
|
return(FALSE);
|
|
}
|
|
LastVEntry->Next->FileVersion = DriverVersion;
|
|
LastVEntry->Next->FileEntry = LastEntry->Next;
|
|
LastVEntry->Next->RefCount = 1;
|
|
LastVEntry->Next->Next = ThisVEntry;
|
|
|
|
return(TRUE);
|
|
|
|
}
|
|
|
|
if( LastEntry == ThisEntry ) {
|
|
//
|
|
// Put it at the very head of the list
|
|
//
|
|
//printf( " Inserting at the head of our list.\n" );
|
|
ThisEntry = MasterFileList;
|
|
MasterFileList = MyMalloc(sizeof(FILE_ENTRY));
|
|
if (!MasterFileList) {
|
|
MasterFileList = ThisEntry;
|
|
return(FALSE);
|
|
}
|
|
MasterFileList->VersionList = MyMalloc(sizeof(VERSION_ENTRY));
|
|
if (!MasterFileList->VersionList) {
|
|
MyFree(MasterFileList);
|
|
MasterFileList = ThisEntry;
|
|
return(FALSE);
|
|
}
|
|
|
|
ThisEntry = LastEntry;
|
|
|
|
MasterFileList->FileName = DriverName;
|
|
MasterFileList->RefCount = 1;
|
|
MasterFileList->Next = LastEntry;
|
|
|
|
MasterFileList->VersionList->FileVersion = DriverVersion;
|
|
MasterFileList->VersionList->FileEntry = MasterFileList;
|
|
MasterFileList->VersionList->Next = NULL;
|
|
MasterFileList->VersionList->RefCount = 1;
|
|
|
|
|
|
} else {
|
|
//
|
|
// insert betwee LastEntry and ThisEntry
|
|
//
|
|
LastEntry->Next = MyMalloc(sizeof(FILE_ENTRY));
|
|
if (!LastEntry->Next) {
|
|
LastEntry->Next = ThisEntry;
|
|
return(FALSE);
|
|
}
|
|
LastEntry->Next->VersionList = MyMalloc(sizeof(VERSION_ENTRY));
|
|
if (!LastEntry->Next->VersionList) {
|
|
MyFree(LastEntry->Next);
|
|
LastEntry->Next = ThisEntry;
|
|
return(FALSE);
|
|
}
|
|
|
|
LastEntry->Next->RefCount = 1;
|
|
LastEntry->Next->Next = ThisEntry;
|
|
LastEntry->Next->FileName = DriverName;
|
|
|
|
LastEntry->Next->VersionList->FileVersion = DriverVersion;
|
|
LastEntry->Next->VersionList->FileEntry = LastEntry->Next;
|
|
LastEntry->Next->VersionList->Next = NULL;
|
|
LastEntry->Next->VersionList->RefCount = 1;
|
|
|
|
|
|
|
|
//printf( " LastEntry: %S DriverEntry: %S NextEntry: %S\n",LastEntry->FileName, DriverName, ThisEntry->FileName );
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
PWSTR
|
|
ExtractAndDuplicateString(
|
|
PWSTR BufferPointer
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Extract a file name from the given buffer, allocate memory and return
|
|
a copy of the extracted string.
|
|
|
|
Arguments:
|
|
|
|
BufferPointer Pointer to a buffer which is assumed to be the start
|
|
of a string. We continue to inspect the incoming
|
|
buffer until we get to the start of an XML tag.
|
|
At that point, assume the string is ending, copy the
|
|
string into a secondary buffer and return that buffer.
|
|
|
|
N.B. The caller is responsible for freeing the memory
|
|
we've allocated!
|
|
|
|
Return Value:
|
|
|
|
Pointer to the allocated memory.
|
|
|
|
NULL if we fail.
|
|
|
|
--*/
|
|
{
|
|
PWSTR TmpPtr = NULL;
|
|
PWSTR ReturnPtr = NULL;
|
|
|
|
TmpPtr = BufferPointer;
|
|
while( TmpPtr && (*TmpPtr) && (*TmpPtr != L'<') ) {
|
|
TmpPtr++;
|
|
}
|
|
|
|
if( *TmpPtr == L'<' ) {
|
|
ULONG SizeInBytes;
|
|
|
|
SizeInBytes = ((TmpPtr - BufferPointer) + 1) * sizeof(WCHAR);
|
|
ReturnPtr = MyMalloc( SizeInBytes );
|
|
wcsncpy( ReturnPtr, BufferPointer, (TmpPtr - BufferPointer) );
|
|
}
|
|
|
|
return ReturnPtr;
|
|
}
|
|
|
|
BOOL
|
|
ProcessFile(
|
|
PTSTR DirectoryName,
|
|
PTSTR FileName
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Parse through the given file (XML file) and remember all the
|
|
driver files specified in it.
|
|
|
|
Arguments:
|
|
|
|
DirectoryName Directory file is present in.
|
|
FileName Name of the file we'll parse.
|
|
|
|
Return Value:
|
|
|
|
TRUE - we successfully inserted the file into our list.
|
|
|
|
FALSE - we failed.
|
|
|
|
--*/
|
|
{
|
|
HANDLE FileHandle = INVALID_HANDLE_VALUE;
|
|
PUCHAR FileBuffer = NULL;
|
|
ULONG i = 0;
|
|
DWORD FileSize = 0;
|
|
BOOLEAN b = FALSE;
|
|
PWSTR MyPtr;
|
|
PWSTR DriverName;
|
|
PWSTR DriverVersion;
|
|
PWSTR ManufacturerName;
|
|
BOOL Status;
|
|
|
|
|
|
|
|
if( !FileName ) {
|
|
return FALSE;
|
|
}
|
|
|
|
_wcslwr( FileName );
|
|
if( wcsstr(FileName,L".cab") ) {
|
|
//
|
|
// They've sent us a cab. Call special code to crack
|
|
// the cab, and extract the xml file into our buffer.
|
|
//
|
|
if (!DiamondExtractFileIntoBuffer(DirectoryName, FileName, &FileBuffer,&FileSize)) {
|
|
return(FALSE);
|
|
}
|
|
} else {
|
|
|
|
FileHandle = CreateFile( FileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL );
|
|
if( FileHandle == INVALID_HANDLE_VALUE) { return(FALSE); }
|
|
FileSize = GetFileSize( FileHandle, NULL );
|
|
if( FileSize == (DWORD)(-1) ) { return(FALSE); };
|
|
|
|
FileBuffer = MyMalloc(FileSize + 3);
|
|
if( FileBuffer == NULL ) {
|
|
// printf( "No System resources!\n" );
|
|
return(FALSE);
|
|
}
|
|
|
|
b = (BOOLEAN)ReadFile( FileHandle, FileBuffer, FileSize, &i, NULL );
|
|
CloseHandle( FileHandle );
|
|
}
|
|
|
|
|
|
//
|
|
// We've got the file up in memory (in FileBuffer), now parse it.
|
|
//
|
|
MyPtr = (PWSTR)FileBuffer;
|
|
while( MyPtr < (PWSTR)(FileBuffer + FileSize - (wcslen(DRIVER_TAG) * sizeof(WCHAR))) ) {
|
|
|
|
// find the driver tag
|
|
if( !_wcsnicmp((MyPtr), DRIVER_TAG, wcslen(DRIVER_TAG)) ) {
|
|
|
|
// FileName tag.
|
|
while( *MyPtr && (_wcsnicmp((MyPtr), FILENAME_TAG, wcslen(FILENAME_TAG))) ) {
|
|
if (MyPtr < (PWSTR)(FileBuffer + FileSize - (wcslen(FILENAME_TAG) * sizeof(WCHAR)))) {
|
|
MyPtr++;
|
|
} else {
|
|
Status = FALSE;
|
|
goto exit;
|
|
}
|
|
}
|
|
MyPtr += wcslen(FILENAME_TAG);
|
|
DriverName = ExtractAndDuplicateString( MyPtr );
|
|
// printf( "Found Driver name %S\n", DriverName );
|
|
|
|
|
|
// Driver Version
|
|
while( *MyPtr && (_wcsnicmp((MyPtr), VERSION_TAG, wcslen(VERSION_TAG))) ) {
|
|
if (MyPtr < (PWSTR)(FileBuffer + FileSize - (wcslen(VERSION_TAG) * sizeof(WCHAR)))) {
|
|
MyPtr++;
|
|
} else {
|
|
Status = FALSE;
|
|
goto exit;
|
|
}
|
|
}
|
|
MyPtr += wcslen(VERSION_TAG);
|
|
DriverVersion = ExtractAndDuplicateString( MyPtr );
|
|
// printf( " Version: %S\n", DriverVersion );
|
|
|
|
|
|
// Manufacturer
|
|
while( *MyPtr && (_wcsnicmp((MyPtr), MANUFACT_TAG, wcslen(MANUFACT_TAG))) ) {
|
|
if (MyPtr < (PWSTR)(FileBuffer + FileSize - (wcslen(MANUFACT_TAG) * sizeof(WCHAR)))) {
|
|
MyPtr++;
|
|
} else {
|
|
Status = FALSE;
|
|
goto exit;
|
|
}
|
|
}
|
|
MyPtr += wcslen(MANUFACT_TAG);
|
|
ManufacturerName = ExtractAndDuplicateString( MyPtr );
|
|
//printf( " Manufacturer name %S\n", ManufacturerName );
|
|
|
|
if( ExcludeMicrosoftDrivers &&
|
|
!_wcsicmp(ManufacturerName, MICROSOFT_MANUFACTURER) ) {
|
|
// skip it.
|
|
// printf( " Skipping Driver: %S\n", DriverName );
|
|
if( DriverName ) {
|
|
MyFree( DriverName );
|
|
}
|
|
if( DriverVersion ) {
|
|
MyFree( DriverVersion );
|
|
}
|
|
} else {
|
|
// printf( " Addinging Driver: %S\n", DriverName );
|
|
AddDriverEntry( DriverName, DriverVersion );
|
|
}
|
|
|
|
MyFree( ManufacturerName );
|
|
|
|
} else {
|
|
if (MyPtr < (PWSTR)(FileBuffer + FileSize)) {
|
|
MyPtr++;
|
|
} else {
|
|
Status = FALSE;
|
|
goto exit;
|
|
}
|
|
}
|
|
}
|
|
|
|
Status = TRUE;
|
|
|
|
exit:
|
|
if( FileBuffer ) {
|
|
MyFree( FileBuffer );
|
|
}
|
|
|
|
return(Status);
|
|
|
|
}
|
|
|
|
VOID
|
|
PrintNode(
|
|
PFILE_ENTRY Entry
|
|
)
|
|
{
|
|
PVERSION_ENTRY V;
|
|
_tprintf( TEXT("%d %s ("), Entry->RefCount, Entry->FileName);
|
|
V = Entry->VersionList;
|
|
while (V) {
|
|
_tprintf( TEXT("%d %s %c"),
|
|
V->RefCount,
|
|
V->FileVersion,
|
|
V->Next
|
|
? TEXT(',')
|
|
: TEXT(')') );
|
|
V = V->Next;
|
|
}
|
|
|
|
_tprintf( TEXT("\r\n"));
|
|
}
|
|
|
|
VOID
|
|
DumpFileList(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Walk our list of files, printing out those which are found on all machines
|
|
and those which are not.
|
|
|
|
Arguments:
|
|
|
|
NONE.
|
|
|
|
Return Value:
|
|
|
|
NONE.
|
|
|
|
--*/
|
|
{
|
|
PFILE_ENTRY MyFileEntry;
|
|
|
|
if( MasterFileList == NULL ) {
|
|
return;
|
|
}
|
|
|
|
#if 0
|
|
_tprintf( TEXT("\nThe following %sdrivers were NOT found in all machines.\n"),
|
|
ExcludeMicrosoftDrivers
|
|
? TEXT("Non-Microsoft ")
|
|
: TEXT("") );
|
|
MyFileEntry = MasterFileList;
|
|
while( MyFileEntry ) {
|
|
if( MyFileEntry->RefCount != FilesProcessed ) {
|
|
PrintNode(MyFileEntry);
|
|
}
|
|
MyFileEntry = MyFileEntry->Next;
|
|
}
|
|
|
|
|
|
_tprintf( TEXT("\nThe following %sdrivers were found in all machines.\n"),
|
|
ExcludeMicrosoftDrivers
|
|
? TEXT("Non-Microsoft ")
|
|
: TEXT("") );
|
|
MyFileEntry = MasterFileList;
|
|
while( MyFileEntry ) {
|
|
if( MyFileEntry->RefCount == FilesProcessed ) {
|
|
PrintNode(MyFileEntry);
|
|
}
|
|
MyFileEntry = MyFileEntry->Next;
|
|
}
|
|
|
|
#else
|
|
MyFileEntry = MasterFileList;
|
|
while( MyFileEntry ) {
|
|
PrintNode(MyFileEntry);
|
|
MyFileEntry = MyFileEntry->Next;
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
}
|
|
|
|
int
|
|
__cdecl
|
|
main( int argc, char *argv[])
|
|
{
|
|
WCHAR TmpDirectoryString[MAX_PATH];
|
|
WCHAR TmpName[MAX_PATH];
|
|
PWSTR p;
|
|
HANDLE FindHandle;
|
|
WIN32_FIND_DATA FoundData;
|
|
DWORD i;
|
|
#if 1
|
|
HANDLE FileHandle;
|
|
DWORD FileSize;
|
|
PVOID FileBuffer;
|
|
BOOL b;
|
|
PSTR DirectoryName,FileName,Ptr,Ptr2;
|
|
CHAR OldChar;
|
|
WCHAR DName[MAX_PATH];
|
|
WCHAR FName[MAX_PATH];
|
|
#endif
|
|
|
|
|
|
//
|
|
// Load Arguments.
|
|
//
|
|
if( argc < 2 ) {
|
|
Usage( argv[0] );
|
|
return 1;
|
|
}
|
|
|
|
if( !_stricmp("/m", argv[1]) || !_stricmp("-m",argv[1]) ) {
|
|
printf( "Exculding all Microsoft Drivers.\n" );
|
|
ExcludeMicrosoftDrivers = TRUE;
|
|
}
|
|
|
|
#if 0
|
|
swprintf( TmpDirectoryString, L"%S", argv[argc-1] );
|
|
|
|
FindHandle = FindFirstFile( TmpDirectoryString, &FoundData );
|
|
if( (FindHandle == INVALID_HANDLE_VALUE) || (FindHandle == NULL) ) {
|
|
printf( "Failed to find file: %S\n", TmpDirectoryString );
|
|
return 0;
|
|
}
|
|
|
|
p = wcsrchr(TmpDirectoryString, L'\\');
|
|
*(p+1) = L'\0';
|
|
|
|
|
|
DiamondInitialize();
|
|
|
|
//
|
|
// Look at every file like this one and populate our driver database.
|
|
//
|
|
do {
|
|
|
|
if( !(FoundData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ) {
|
|
|
|
//printf( " Processing file: %S\n", FoundData.cFileName );
|
|
|
|
if (ProcessFile( TmpDirectoryString, FoundData.cFileName )) {
|
|
FilesProcessed++;
|
|
}
|
|
|
|
}
|
|
} while( FindNextFile( FindHandle, &FoundData ) );
|
|
#else
|
|
|
|
DiamondInitialize();
|
|
|
|
swprintf( TmpDirectoryString, L"%S", argv[argc-1] );
|
|
FileHandle = CreateFile( TmpDirectoryString, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL );
|
|
if( FileHandle == INVALID_HANDLE_VALUE) { return(FALSE); }
|
|
FileSize = GetFileSize( FileHandle, NULL );
|
|
if( FileSize == (DWORD)(-1) ) { return(FALSE); };
|
|
|
|
FileBuffer = MyMalloc(FileSize + 3);
|
|
if( FileBuffer == NULL ) {
|
|
return -1;
|
|
}
|
|
|
|
b = (BOOLEAN)ReadFile( FileHandle, FileBuffer, FileSize, &i, NULL );
|
|
CloseHandle( FileHandle );
|
|
|
|
Ptr = (PSTR)FileBuffer;
|
|
while(Ptr < (PCHAR)FileBuffer + FileSize) {
|
|
Ptr2 = DirectoryName = Ptr;
|
|
while(*Ptr2 != '\r') {
|
|
Ptr2++;
|
|
}
|
|
Ptr = Ptr2+2;
|
|
*Ptr2 = '\0';
|
|
|
|
Ptr2 = strrchr(DirectoryName, '\\');
|
|
Ptr2+=1;
|
|
FileName = Ptr2;
|
|
OldChar = *Ptr2;
|
|
*Ptr2 = '\0';
|
|
swprintf( DName, L"%S", DirectoryName );
|
|
|
|
*Ptr2 = OldChar;
|
|
swprintf( FName, L"%S", FileName );
|
|
|
|
//printf( " Processing file: %s\n", FileName );
|
|
|
|
if (ProcessFile( DName, FName )) {
|
|
//printf( " Successfully processed: %s\n", FileName );
|
|
FilesProcessed++;
|
|
} else {
|
|
//printf( " Failed to process: %s\n", FileName );
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
//
|
|
// Print out one of the lists. They should all be the same.
|
|
//
|
|
|
|
printf("Sucessfully processed %d files.\r\n", FilesProcessed);
|
|
DumpFileList();
|
|
|
|
|
|
DiamondTerminate();
|
|
return 0;
|
|
|
|
}
|
|
|
|
|