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.
 
 
 
 
 
 

448 lines
11 KiB

/*==========================================================================
*
* Copyright (C) 1996 Microsoft Corporation. All Rights Reserved.
*
* File: apphack.c
* Content: app compatiblity hacking code
* History:
* Date By Reason
* ==== == ======
* 27-may-96 craige initial implementation
* 28-sep-96 craige allow binary data in registry (f*cking .inf
* can't put in dword into the registry)
*
***************************************************************************/
#include "ddrawpr.h"
#include "apphack.h"
#define STRCMP lstrcmpi
static int sortRtn( LPAPPHACKS *p1, LPAPPHACKS *p2 )
{
return STRCMP( (*p1)->szName, (*p2)->szName );
}
static int searchRtn( LPSTR key, LPAPPHACKS *p2 )
{
return STRCMP( key, (*p2)->szName );
}
__inline static BOOL fileRead( HANDLE hfile, void *data, int len )
{
DWORD len_read;
if( !ReadFile( hfile, data, (DWORD) len, &len_read, NULL ) ||
len_read != (DWORD) len )
{
return FALSE;
}
return TRUE;
} /* fileRead */
__inline static BOOL fileSeek( HANDLE hfile, DWORD offset )
{
if( SetFilePointer( hfile, offset, NULL, FILE_BEGIN ) != offset )
{
return FALSE;
}
return TRUE;
} /* fileSeek */
void FreeAppHackData(void)
{
LPAPPHACKS next;
LPAPPHACKS lphack = lpAppList;
while( lphack != NULL )
{
next = lphack->lpNext;
MemFree( lphack );
lphack = next;
}
if( lpAppArray != NULL )
{
MemFree( lpAppArray );
}
lpAppArray = NULL;
lpAppList = NULL;
dwAppArraySize = 0;
bHaveReadReg = FALSE;
}
/*
* HackMeBaby
*
* And we'll have fun fun fun 'til your daddy takes your app hacks away...
*/
DWORD HackMeBaby( void )
{
char fname[_MAX_PATH];
char name[_MAX_PATH];
HANDLE hfile;
int i;
LPAPPHACKS lphack;
LPAPPHACKS *lplphack;
DWORD dwScreenSaver;
IMAGE_NT_HEADERS nth;
IMAGE_DOS_HEADER dh;
DWORD appid;
HKEY hkey;
/*
* bail on the existing info if requested
*/
if( bReloadReg )
{
DPF( 3, "Reloading the compatibility info from the registry" );
if( lpAppList != NULL )
{
DPF( 4, "Freeing existing compatiblity list" );
}
FreeAppHackData();
}
/*
* read the registry for any app hacks
*/
if( !bHaveReadReg )
{
int index;
int count;
bHaveReadReg = TRUE;
if( !RegOpenKey( HKEY_LOCAL_MACHINE,
REGSTR_PATH_DDRAW "\\" REGSTR_KEY_APPCOMPAT, &hkey ) )
{
index = 0;
count = 0;
DPF( 4, "Reading App Compatiblity Information" );
/*
* run through all keys
*/
while( !RegEnumKey( hkey, index, name, sizeof( name ) ) )
{
HKEY hsubkey;
DPF( 5, " Found info for %s", name );
/*
* get info for this specific app
*/
if( !RegOpenKey( hkey, name, &hsubkey ) )
{
DWORD type;
DWORD cb;
DWORD id;
DWORD flags;
cb = sizeof( name );
if( !RegQueryValueEx( hsubkey, REGSTR_VAL_DDRAW_NAME,
NULL, &type, name, &cb ) )
{
if( type == REG_SZ )
{
cb = sizeof( flags );
if( !RegQueryValueEx( hsubkey, REGSTR_VAL_DDRAW_FLAGS,
NULL, &type, (LPSTR) &flags, &cb ) )
{
if( (type == REG_DWORD) ||
(type == REG_BINARY && cb == sizeof( flags )) )
{
if( !(flags & ~DDRAW_APPCOMPAT_VALID) )
{
cb = 4;
if( !RegQueryValueEx( hsubkey, REGSTR_VAL_DDRAW_APPID,
NULL, &type, (LPSTR) &id, &cb ) )
{
if( (type == REG_DWORD) ||
(type == REG_BINARY && cb == sizeof( flags )) )
{
/*
* finally! we have all the data. save it
*/
lphack = MemAlloc( sizeof( *lphack ) + strlen( name ) + 1 );
if( lphack != NULL )
{
lphack->dwAppId = id;
lphack->dwFlags = flags;
lphack->szName = &((LPSTR)lphack)[sizeof( *lphack )];
lphack->lpNext = lpAppList;
lpAppList = lphack;
strcpy( lphack->szName, name );
count++;
DPF( 5, " Name = %s", lphack->szName );
DPF( 5, " Flags = 0x%08lx", lphack->dwFlags );
DPF( 5, " AppId = 0x%08lx", lphack->dwAppId );
}
else
{
DPF( 0, " Out of memory!!!" );
}
}
else
{
DPF( 0, " AppID not a DWORD for app %s", name );
}
}
}
else
{
DPF( 0, " Invalid flags %08lx for app %s", flags, name );
}
}
else
{
DPF( 0, " Flags not a DWORD for app %s", name );
}
}
else
{
DPF( 0, " No flags found for app %s", name );
}
}
else
{
DPF( 0, " Executable name not a string!!!" );
}
}
else
{
DPF( 0, " Executable name not found!!!" );
}
RegCloseKey( hsubkey );
}
else
{
DPF( 0, " RegOpenKey for %ld FAILED!" );
}
/*
* next reg entry...
*/
index++;
}
DPF( 5, "Enumerated %ld keys, found %ld valid ones", index, count );
/*
* go make an array we can sort and use later...
*/
if( count > 0 )
{
lpAppArray = MemAlloc( (count+1) * sizeof( LPAPPHACKS ) );
if( lpAppArray != NULL )
{
LPAPPHACKS lphack;
dwAppArraySize = 0;
lphack = lpAppList;
while( lphack != NULL )
{
lpAppArray[ dwAppArraySize ] = lphack;
lphack = lphack->lpNext;
dwAppArraySize++;
}
qsort( lpAppArray, count, sizeof( LPAPPHACKS ),
(LPVOID) sortRtn );
}
for( count = 0; count< (int) dwAppArraySize; count++ )
{
DPF( 5, " %s", lpAppArray[count]->szName );
}
}
RegCloseKey( hkey );
}
else
{
#ifdef WIN95
DPF( 0, "Failed to find registry root" );
#endif
}
/*
* The first time through, we will also check to see if a gamma
* calibrator is registered. All we'll do here is read the registry
* key and if it's non-NULL, we'll assume that one exists.
*/
if( !RegOpenKey( HKEY_LOCAL_MACHINE,
REGSTR_PATH_DDRAW "\\" REGSTR_KEY_GAMMA_CALIBRATOR, &hkey ) )
{
DWORD type;
DWORD cb;
cb = sizeof( szGammaCalibrator );
if( !RegQueryValueEx( hkey, REGSTR_VAL_GAMMA_CALIBRATOR,
NULL, &type, szGammaCalibrator, &cb ) )
{
if( ( type == REG_SZ ) &&
( szGammaCalibrator[0] != '\0' ) )
{
bGammaCalibratorExists = TRUE;
}
}
RegCloseKey( hkey );
}
}
else
{
DPF( 3, "Registry already scanned, not doing it again" );
}
/*
* find out what process we are dealing with
*/
hfile = GetModuleHandle( NULL );
GetModuleFileName( hfile, fname, sizeof( fname ) );
DPF( 5, "full name = %s", fname );
i = strlen( fname )-1;
while( i >=0 && fname[i] != '\\' )
{
i--;
}
i++;
strcpy( name, &fname[i] );
DPF( 5, "name = %s", name );
lplphack = bsearch( name, lpAppArray, dwAppArraySize, sizeof( LPAPPHACKS ),
(LPVOID) searchRtn );
/*
* If it has an .SCR extension, assume it's a screensaver.
*/
dwScreenSaver = 0;
#ifdef WIN95
if( ( strlen(name) > 4 ) && !STRCMP( &name[ strlen(name) - 4 ], ".SCR" ) )
{
dwScreenSaver = DDRAW_APPCOMPAT_SCREENSAVER;
}
#endif
/*
* go find the timestamp in the file
*/
appid = 0;
do
{
hfile = CreateFile( fname, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
if( hfile == INVALID_HANDLE_VALUE )
{
DPF( 0, "Could not open file %s", fname );
break;
}
if( !fileRead( hfile, &dh, sizeof( dh ) ) )
{
DPF( 0, "Could not read DOS header for file %s", fname );
break;
}
if( dh.e_magic != IMAGE_DOS_SIGNATURE )
{
DPF( 0, "Invalid DOS header for file %s", fname );
break;
}
if( !fileSeek( hfile, dh.e_lfanew ) )
{
DPF( 0, "Could not seek to PE header in file %s", fname );
break;
}
if( !fileRead( hfile, &nth, sizeof( nth ) ) )
{
DPF( 0, "Could not read PE header for file %s", fname );
break;
}
if( nth.Signature != IMAGE_NT_SIGNATURE )
{
DPF( 0, "Bogus PE header for file %s", fname );
break;
}
appid = nth.FileHeader.TimeDateStamp;
if( appid == 0 )
{
DPF( 0, "TimeDataStap is 0 for file %s", fname );
break;
}
DPF( 5, "Obtained appid: 0x%08lx", appid );
CloseHandle( hfile );
hfile = NULL;
} while(0); //fake try-except
// Now write the values into some known place
if (appid)
{
DWORD dw;
if( !RegCreateKey( HKEY_LOCAL_MACHINE,
REGSTR_PATH_DDRAW "\\" REGSTR_KEY_LASTAPP, &hkey ) )
{
RegSetValueEx(hkey, REGSTR_VAL_DDRAW_NAME, 0, REG_SZ, (LPBYTE)name, strlen(name)+1);
RegSetValueEx(hkey, REGSTR_VAL_DDRAW_APPID, 0, REG_DWORD, (LPBYTE)&appid, sizeof(appid));
RegCloseKey(hkey);
}
}
if( lplphack != NULL && appid )
{
HANDLE hfile;
/*
* back up to the first match with this name
*/
lphack = *lplphack;
while( lplphack != lpAppArray )
{
lplphack--;
if( STRCMP( (*lplphack)->szName, name ) )
{
lplphack++;
break;
}
lphack = *lplphack;
}
/*
* now run through all matches we found
*/
hfile = NULL;
while( 1 )
{
/*
* is this one of the ones that matches the calling process?
*/
if( *lplphack == NULL )
{
break;
}
lphack = *lplphack;
if( STRCMP( lphack->szName, name ) )
{
break;
}
/*
* validate timestamp in registry against the one in the file
*/
if( lphack->dwAppId == appid )
{
DPF( 5, "****** Compatiblity data 0x%08lx found for %s",
lphack->dwFlags, name );
return lphack->dwFlags | dwScreenSaver;
}
lplphack++;
}
if( hfile != NULL )
{
CloseHandle( hfile );
}
}
return dwScreenSaver;
} /* HackMeBaby */