961 lines
29 KiB
C
961 lines
29 KiB
C
/*
|
|
|
|
Copyright (c) 1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
appcompat.c
|
|
|
|
Abstract:
|
|
An application to launch a required APP with the
|
|
version and the APPCOMPAT flags set.
|
|
|
|
*/
|
|
|
|
/* INCLUDES */
|
|
|
|
#define UNICODE 1
|
|
|
|
#include <windows.h>
|
|
#include <commdlg.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
#include <stdio.h>
|
|
#include <shellapi.h>
|
|
#include <tchar.h>
|
|
#include <htmlhelp.h>
|
|
#include <apcompat.h>
|
|
|
|
#include "appcompat.h"
|
|
|
|
|
|
#define MAXRES 256
|
|
#define MAXKEY 100
|
|
#define MAXDATA 10
|
|
#define MAXTITLE 100
|
|
|
|
|
|
|
|
INT_PTR CALLBACK DialogProc(HWND, UINT, WPARAM, LPARAM);
|
|
int MakeAppCompatGoo(TCHAR*, LARGE_INTEGER*, UINT);
|
|
long DeleteSpecificVal(HKEY );
|
|
extern TCHAR* CheckExtension(TCHAR*);
|
|
/* Global */
|
|
// Pattern string.. MajorVersion, MinorVersion, BuildNumber,ServicePackMajor, ServicePackMinor,
|
|
// PlatformID, CSDVersion string....
|
|
const TCHAR* pVersionVal[] = {
|
|
TEXT("4,0,1381,3,0,2,Service Pack 3"),
|
|
TEXT("4,0,1381,4,0,2,Service Pack 4"),
|
|
TEXT("4,0,1381,5,0,2,Service Pack 5"),
|
|
TEXT("4,10,1998,0,0,1,"),
|
|
TEXT("4,0,950,0,0,1,"),
|
|
NULL
|
|
};
|
|
|
|
#define MAXVERNUM ( sizeof(pVersionVal)/sizeof(TCHAR*) ) - 1
|
|
|
|
const TCHAR szFilter[] = TEXT("EXE Files (*.EXE)\0*.exe\0") \
|
|
TEXT("All Files (*.*)\0*.*\0\0");
|
|
|
|
HINSTANCE g_hInstance;
|
|
extern PVOID g_lpPrevRegSettings;
|
|
BOOL g_fAppCompatGoo = FALSE;
|
|
BOOLEAN g_fNotPermanent = FALSE;
|
|
extern BOOLEAN g_GooAppendFlag;
|
|
|
|
|
|
// Converts Text to interger.
|
|
int TextToInt(
|
|
const TCHAR *nptr
|
|
)
|
|
{
|
|
int c; /* current char */
|
|
int total; /* current total */
|
|
int sign; /* if '-', then negative, otherwise positive */
|
|
|
|
/* skip whitespace */
|
|
while ( *nptr == TEXT(' ') )
|
|
++nptr;
|
|
|
|
c = (int)*nptr++;
|
|
sign = c; /* save sign indication */
|
|
if (c == TEXT('-') || c == TEXT('+') )
|
|
c = (int)*nptr++; /* skip sign */
|
|
total = 0;
|
|
|
|
while ( (c>=TEXT('0')) && (c <= TEXT('9')) ) {
|
|
total = 10 * total + (c - TEXT('0') ); /* accumulate digit */
|
|
c = (int)*nptr++; /* get next char */
|
|
}
|
|
|
|
if (sign == '-')
|
|
return -total;
|
|
else
|
|
return total; /* return result, negated if necessary */
|
|
}
|
|
|
|
|
|
TCHAR* CheckExtension(TCHAR* szTitle)
|
|
{
|
|
TCHAR *pCh;
|
|
pCh = szTitle;
|
|
|
|
while(*pCh != TEXT('.'))
|
|
{
|
|
if(*pCh == TEXT('\0'))
|
|
break;
|
|
pCh++;
|
|
}
|
|
if(*pCh == TEXT('\0'))
|
|
return NULL;
|
|
else
|
|
{
|
|
pCh++;
|
|
return pCh;
|
|
}
|
|
}
|
|
|
|
|
|
VOID GetTitleAndCommandLine(TCHAR* pEditBuf, TCHAR* pszTitle, TCHAR* pszCommandLine)
|
|
{
|
|
TCHAR szTitleAndCommandLine[_MAX_PATH];
|
|
TCHAR* pszTemp, *pszTmpTitle;
|
|
UINT i = 0;
|
|
|
|
lstrcpy(szTitleAndCommandLine, pEditBuf);
|
|
pszTmpTitle = pszTemp = szTitleAndCommandLine;
|
|
|
|
if(*pszTemp == TEXT('\"') ){ // The title has quotes(" "). It has command line params.
|
|
pszTemp++;
|
|
while(*pszTemp != TEXT('\"') ){
|
|
pszTemp++;
|
|
if(*pszTemp == TEXT('\0') )
|
|
break;
|
|
if(*pszTemp == TEXT('\\') )
|
|
pszTmpTitle = pszTemp + 1;
|
|
}
|
|
|
|
}
|
|
else{ // No quotes(" ")...This means that there are no command line parameters.
|
|
GetFileTitle(pEditBuf,pszTitle,MAX_PATH);
|
|
pszCommandLine = NULL;
|
|
return;
|
|
}
|
|
|
|
RtlZeroMemory(pszCommandLine, MAX_PATH);
|
|
if(*pszTemp != TEXT('\0') ){ // There are command line paramaters for the APP.
|
|
*(pszTemp ) = TEXT('\0');
|
|
lstrcpy(pEditBuf, szTitleAndCommandLine);
|
|
|
|
// For Paths beginning with a '"' and ending with a '"'.
|
|
if(*pEditBuf == TEXT('\"') )
|
|
lstrcat(pEditBuf, TEXT("\"") );
|
|
// Now copy over the Command line parameters.
|
|
pszTemp++;
|
|
while( (*pszTemp) != TEXT('\0') ){
|
|
*(pszCommandLine + i) = *pszTemp;
|
|
i++;
|
|
pszTemp++;
|
|
}
|
|
*(pszCommandLine + i) = TEXT('\0');
|
|
}
|
|
|
|
lstrcpy(pszTitle, pszTmpTitle);
|
|
}
|
|
|
|
VOID GetFileExtension(TCHAR* pEditBuf, TCHAR* pszTitle,TCHAR* pszCommandLine)
|
|
{
|
|
GetTitleAndCommandLine(pEditBuf, pszTitle, pszCommandLine);
|
|
if(CheckExtension(pszTitle) == NULL)
|
|
lstrcat(pszTitle,TEXT(".exe"));
|
|
}
|
|
|
|
TCHAR* GetNextWord(BOOLEAN* pfEndOfLine,TCHAR* pStr)
|
|
{
|
|
TCHAR* pCh;
|
|
|
|
pCh = pStr;
|
|
//Skip white spaces..
|
|
while((*pCh == TEXT(' ')) || (*pCh == TEXT('\t')))
|
|
pCh++;
|
|
|
|
// Fix for Command line parameters (from the command line within " " :)) ).
|
|
if( *pCh == TEXT('\"') ){
|
|
pCh++;
|
|
while( *pCh != TEXT('\0') ) // Scan till the end when the string starts with a '"'.
|
|
pCh++;
|
|
*pfEndOfLine = TRUE;
|
|
return pCh;
|
|
}
|
|
// End ..Fix for Command line parameters (from the command line within " " :)) ).
|
|
|
|
while( ((*pCh)!=TEXT('-')) && ((*pCh)!=TEXT('\0')) )
|
|
{
|
|
pCh++;
|
|
}
|
|
if((*pCh) == TEXT('\0'))
|
|
*pfEndOfLine = TRUE;
|
|
else
|
|
*pfEndOfLine = FALSE;
|
|
|
|
return pCh;
|
|
}
|
|
|
|
void SkipBlanks(TCHAR* pStr)
|
|
{
|
|
TCHAR* pTemp;
|
|
|
|
if(*(pStr - 1) == TEXT(' '))
|
|
{
|
|
pTemp = pStr;
|
|
while(*(pTemp - 1) == TEXT(' '))
|
|
pTemp--;
|
|
*pTemp = TEXT('\0');
|
|
}
|
|
}
|
|
|
|
VOID SetRegistryVal(TCHAR* szTitle, TCHAR* szVal,PTCHAR szBuffer,DWORD dwType)
|
|
{
|
|
long lResult;
|
|
TCHAR szSubKey[MAXKEY];
|
|
HKEY hKey;
|
|
|
|
wsprintf(szSubKey, TEXT("software\\microsoft\\windows NT\\currentversion\\Image File Execution Options\\%s"),szTitle);
|
|
|
|
lResult = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
|
|
szSubKey,
|
|
0,
|
|
TEXT("\0"),
|
|
0,
|
|
KEY_WRITE,
|
|
NULL,
|
|
&hKey,
|
|
NULL);
|
|
if(lResult == ERROR_SUCCESS)
|
|
{
|
|
|
|
RegSetValueEx(hKey,szVal,
|
|
0, dwType,(CONST BYTE*)szBuffer, lstrlen(szBuffer) + 1);
|
|
|
|
RegCloseKey(hKey);
|
|
}
|
|
}
|
|
|
|
long RestoreRegistryVal(szTitle)
|
|
{
|
|
long lResult;
|
|
TCHAR szSubKey[MAXKEY];
|
|
HKEY hKey;
|
|
|
|
wsprintf(szSubKey, TEXT("software\\microsoft\\windows NT\\currentversion\\Image File Execution Options\\%s"),szTitle);
|
|
|
|
lResult = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
|
|
szSubKey,
|
|
0,
|
|
TEXT("\0"),
|
|
0,
|
|
KEY_WRITE,
|
|
NULL,
|
|
&hKey,
|
|
NULL);
|
|
if(lResult == ERROR_SUCCESS)
|
|
{
|
|
|
|
lResult = RegSetValueEx(hKey,TEXT("ApplicationGoo"),
|
|
0, REG_BINARY,(CONST BYTE*)g_lpPrevRegSettings, *((PULONG)g_lpPrevRegSettings) );
|
|
|
|
if(ERROR_SUCCESS != lResult)
|
|
MessageBox(NULL,TEXT("Appending ApplicationGoo failed !!"),TEXT(""),IDOK);
|
|
|
|
RegCloseKey(hKey);
|
|
}
|
|
return lResult;
|
|
}
|
|
|
|
long DeleteKey(TCHAR* szTitle, BOOL bGooKeyPresent)
|
|
{
|
|
long lRet;
|
|
HKEY hKey;
|
|
|
|
lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
|
TEXT("software\\microsoft\\windows NT\\currentversion\\Image File Execution Options"),
|
|
0,
|
|
KEY_WRITE,
|
|
&hKey);
|
|
|
|
if(ERROR_SUCCESS == lRet){
|
|
if((!g_fAppCompatGoo) &&
|
|
( TRUE == bGooKeyPresent) ){ // We did not set ApplicationGoo at all. So, we cannot delete it !
|
|
lRet = DeleteSpecificVal(hKey);
|
|
return lRet;
|
|
}
|
|
RegDeleteKey(hKey, szTitle);
|
|
RegCloseKey(hKey);
|
|
// If there was a previous entry of ApplicationGoo in the registry.
|
|
if(g_GooAppendFlag)
|
|
lRet = RestoreRegistryVal(szTitle);
|
|
|
|
}// If ERROR_SUCCESS
|
|
return lRet;
|
|
}
|
|
|
|
long DeleteSpecificVal(HKEY hKey)
|
|
{
|
|
if(g_fNotPermanent == TRUE){
|
|
if(g_fAppCompatGoo){
|
|
RegDeleteValue(hKey, TEXT("ApplicationGoo") );
|
|
if(g_GooAppendFlag){
|
|
if( RegSetValueEx(hKey,
|
|
TEXT("ApplicationGoo"),
|
|
0,
|
|
REG_BINARY,
|
|
(CONST BYTE*)g_lpPrevRegSettings,
|
|
*((PULONG)g_lpPrevRegSettings)
|
|
) != ERROR_SUCCESS )
|
|
MessageBox(NULL,TEXT("Appending ApplicationGoo failed !!"),TEXT(""),IDOK);
|
|
}
|
|
}
|
|
}
|
|
return( RegDeleteValue( hKey,TEXT("DisableHeapLookAside") ) );
|
|
}
|
|
|
|
long CheckAndDeleteKey(TCHAR* szTitle, BOOL Check)
|
|
{
|
|
long lResult,lRet = -1;
|
|
TCHAR szSubKey[MAXKEY], szData[MAXDATA], szKeyName[MAXKEY],szResult[MAXDATA];
|
|
int Size,KeyLength, indx =0;
|
|
HKEY hKey;
|
|
DWORD dwType;
|
|
BOOLEAN bSpecificKey = FALSE, bGooKeyPresent = FALSE;
|
|
|
|
wsprintf(szSubKey,TEXT("software\\microsoft\\windows NT\\currentversion\\Image File Execution Options\\%s"),szTitle);
|
|
|
|
lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
|
szSubKey,
|
|
0,
|
|
KEY_SET_VALUE | KEY_QUERY_VALUE,
|
|
&hKey);
|
|
|
|
if(ERROR_SUCCESS == lResult){
|
|
Size = sizeof(szData) + 1;
|
|
lResult = RegQueryValueEx(hKey,
|
|
TEXT("DisableHeapLookAside"),
|
|
NULL,
|
|
&dwType,
|
|
(LPBYTE)szData,
|
|
&Size);
|
|
if(Check)
|
|
return lResult;
|
|
|
|
/*
|
|
This is done to check whether this is the only value under this KEY.
|
|
If there are other values under this key, only this value is deleted
|
|
*/
|
|
KeyLength = sizeof(szKeyName) + 1;
|
|
while(RegEnumValue(hKey,
|
|
indx,
|
|
szKeyName,
|
|
&KeyLength,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL) != ERROR_NO_MORE_ITEMS)
|
|
{
|
|
if(lstrcmpi(szKeyName,TEXT("DisableHeapLookAside"))!=0){
|
|
if(lstrcmpi(szKeyName,TEXT("ApplicationGoo"))!=0 ||
|
|
g_fNotPermanent == FALSE){ // ApplicationGoo is present but it should be permanent...
|
|
bSpecificKey = TRUE;
|
|
lRet = DeleteSpecificVal(hKey);
|
|
break;
|
|
}
|
|
bGooKeyPresent = TRUE; // If it has come here, then it is equal to "ApplicationGoo"
|
|
}
|
|
indx++;
|
|
KeyLength = sizeof(szKeyName) + 1;
|
|
}
|
|
RegCloseKey(hKey);
|
|
|
|
if(!bSpecificKey){
|
|
lRet = DeleteKey(szTitle, bGooKeyPresent);
|
|
}
|
|
|
|
}
|
|
return lRet;
|
|
}
|
|
|
|
|
|
|
|
void DetailError(DWORD dwErrMsg)
|
|
{
|
|
LPVOID lpMsgBuf;
|
|
if(FormatMessage(
|
|
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
|
FORMAT_MESSAGE_FROM_SYSTEM |
|
|
FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
NULL,
|
|
dwErrMsg,
|
|
MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),
|
|
(LPTSTR)&lpMsgBuf,
|
|
0,
|
|
NULL
|
|
) != 0){
|
|
MessageBox(NULL, lpMsgBuf, TEXT(""), IDOK);
|
|
}
|
|
LocalFree(lpMsgBuf);
|
|
}
|
|
|
|
|
|
|
|
VOID ExecuteApp(HWND hWnd, TCHAR* AppName,TCHAR* szTitle,TCHAR* pszCommandLine, BOOLEAN fMask)
|
|
{
|
|
SHELLEXECUTEINFO sei;
|
|
MSG msg;
|
|
static int cnt = 0;
|
|
|
|
memset(&sei, 0, sizeof(SHELLEXECUTEINFO) );
|
|
sei.cbSize = sizeof(SHELLEXECUTEINFO);
|
|
sei.hwnd = hWnd;
|
|
sei.lpVerb = TEXT("open");
|
|
sei.lpFile = AppName;
|
|
sei.nShow = SW_SHOWDEFAULT;
|
|
sei.lpParameters = pszCommandLine;
|
|
|
|
if(fMask){
|
|
sei.fMask = SEE_MASK_NOCLOSEPROCESS;
|
|
}
|
|
if(ShellExecuteEx(&sei) == FALSE) { /* If the API fails */
|
|
CheckAndDeleteKey(szTitle, FALSE);
|
|
DetailError( GetLastError() );
|
|
}
|
|
else{ // Was successful in launching the application.
|
|
// Wait till the process terminates...
|
|
if(fMask){
|
|
if(NULL != sei.hProcess ){ // The hProcess can be NULL sometimes....
|
|
while(WaitForSingleObject(sei.hProcess, 5000)== WAIT_TIMEOUT){
|
|
while(PeekMessage(&msg, NULL, 0, 0,PM_REMOVE)){
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
}
|
|
cnt++;
|
|
if(cnt == 15)
|
|
break;
|
|
}
|
|
CheckAndDeleteKey(szTitle, FALSE );
|
|
CloseHandle(sei.hProcess);
|
|
}
|
|
else
|
|
MessageBox(NULL, TEXT(" Process Handle is NULL"), TEXT(""), IDOK);
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|
|
VOID SetTempPath(VOID)
|
|
{
|
|
TCHAR szEnv[_MAX_PATH],szTemp[_MAX_PATH];
|
|
int indx1=0,indx2 =0;
|
|
|
|
GetEnvironmentVariable(TEXT("TEMP"),szTemp,_MAX_PATH);
|
|
|
|
szEnv[0] = szTemp[0];
|
|
lstrcpy(&szEnv[1],TEXT(":\\Temp"));
|
|
if(SetEnvironmentVariable(TEXT("TEMP"), szEnv) == 0){
|
|
DetailError(GetLastError());
|
|
}
|
|
}
|
|
|
|
VOID GetDirectoryPath(LPTSTR pszModulePath,LPTSTR pszDirectoryPath)
|
|
{
|
|
TCHAR* pTmp, *pSwap;
|
|
|
|
pTmp = (TCHAR*) malloc( sizeof(TCHAR) * (lstrlen((LPCTSTR)pszModulePath) + 1) );
|
|
if(pTmp){
|
|
lstrcpy(pTmp, pszModulePath);
|
|
pSwap = pTmp;
|
|
pTmp += lstrlen((LPCTSTR)pszModulePath);
|
|
while(*pTmp != TEXT('\\') ){
|
|
pTmp--;
|
|
}
|
|
*pTmp = TEXT('\0');
|
|
pTmp = pSwap;
|
|
lstrcpy(pszDirectoryPath, pTmp);
|
|
free(pTmp);
|
|
}
|
|
}
|
|
|
|
VOID GetHelpPath(LPTSTR pszPath)
|
|
{
|
|
TCHAR szFilePath[_MAX_PATH] = {0};
|
|
|
|
GetModuleFileName(NULL,szFilePath,_MAX_PATH);
|
|
GetDirectoryPath(szFilePath, pszPath);
|
|
lstrcat(pszPath, TEXT("\\w2rksupp.chm") );
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Main Entry point */
|
|
|
|
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
|
|
LPSTR lpszCmdLine, int nCmdShow)
|
|
{
|
|
const static TCHAR szAppName [] = TEXT("AppCompat");
|
|
MSG msg;
|
|
WNDCLASS wndclass;
|
|
|
|
/* Addition for Command line Parameters*/
|
|
TCHAR *AppName = NULL, *pCh = NULL, *pNextWord=NULL;
|
|
BOOLEAN fEnd = FALSE, fDisableHeapLookAside = FALSE, fSetTemp = FALSE,fHelpDisplay = FALSE;
|
|
BOOL fKeepRegistrySetting = FALSE;
|
|
UINT VersionNum = 5,indx,length;
|
|
HKEY hKey;
|
|
TCHAR szTitle[_MAX_PATH], szSubKey[MAXKEY],szKeyName[MAXKEY];
|
|
TCHAR szCommandLine[_MAX_PATH];
|
|
LPTSTR pStr;
|
|
long lResult;
|
|
LPTSTR lpszCommandLn;
|
|
TCHAR szDirectoryPath[_MAX_PATH];
|
|
HWND hHelpWnd;
|
|
static LARGE_INTEGER AppCompatFlag;
|
|
static TCHAR szCurDir[MAX_PATH];
|
|
|
|
g_hInstance = hInstance;
|
|
// For Unicode
|
|
lpszCommandLn = GetCommandLine();
|
|
pStr = (TCHAR*)malloc( sizeof(TCHAR) * ( lstrlen((LPCTSTR)lpszCommandLn) + 1) );
|
|
if(pStr != NULL)
|
|
{
|
|
lstrcpy(pStr, (LPCTSTR)lpszCommandLn);
|
|
pCh = pStr;
|
|
}
|
|
else{
|
|
return 0;
|
|
}
|
|
// Skip till the first delimiter
|
|
while(*pCh != TEXT('-') ){
|
|
if(*pCh == TEXT('\0') )
|
|
break;
|
|
pCh++;
|
|
}
|
|
|
|
if(*pCh == TEXT('-') )
|
|
{
|
|
pCh++; /* If '-' is found, skip to the next
|
|
character */
|
|
if(*pCh != TEXT('\0') ){
|
|
do
|
|
{
|
|
pCh++;
|
|
pNextWord = GetNextWord(&fEnd,pCh);
|
|
switch(LOWORD( CharLower((LPTSTR)*(pCh - 1))) )
|
|
{
|
|
|
|
case TEXT('d'):
|
|
/* For Disable Heap look-aside */
|
|
fDisableHeapLookAside = TRUE;
|
|
break;
|
|
|
|
case TEXT('k'):
|
|
/* For Keep the Registry settings */
|
|
fKeepRegistrySetting = TRUE;
|
|
break;
|
|
|
|
case TEXT('g'):
|
|
/* For GetDiskFreespace in AppCompatGoo registry setting */
|
|
g_fAppCompatGoo = TRUE;
|
|
AppCompatFlag.LowPart |= KACF_GETDISKFREESPACE;
|
|
break;
|
|
|
|
#ifdef EXTRA_APP_COMPAT
|
|
case TEXT('f'): // Pre-Windows 2000 Free Threading Model(FTM).
|
|
g_fAppCompatGoo = TRUE;
|
|
AppCompatFlag.LowPart |= KACF_FTMFROMCURRENTAPT;
|
|
break;
|
|
|
|
case TEXT('o'):
|
|
g_fAppCompatGoo = TRUE;
|
|
AppCompatFlag.LowPart |=KACF_OLDGETSHORTPATHNAME;
|
|
#endif
|
|
|
|
case TEXT('t'):
|
|
/* For Disable Heap look-aside */
|
|
fSetTemp = TRUE;
|
|
g_fAppCompatGoo = TRUE;
|
|
AppCompatFlag.LowPart |=KACF_GETTEMPPATH;
|
|
break;
|
|
|
|
case TEXT('v'):
|
|
SkipBlanks(pNextWord);
|
|
VersionNum = TextToInt((LPCTSTR)pCh) - 1;
|
|
if(VersionNum >= MAXVERNUM) {
|
|
|
|
fHelpDisplay = TRUE;
|
|
GetHelpPath(szDirectoryPath);
|
|
hHelpWnd = HtmlHelp(NULL, szDirectoryPath, HH_DISPLAY_TOPIC,
|
|
(DWORD_PTR)IDHH_CMDSYNTAX );
|
|
while(IsWindow(hHelpWnd) )
|
|
Sleep(200);
|
|
|
|
return 0;
|
|
//break;
|
|
}
|
|
// Set the appcompatgoo flag .
|
|
if(VersionNum <= (MAXVERNUM - 1)){
|
|
g_fAppCompatGoo = TRUE;
|
|
AppCompatFlag.LowPart |= KACF_VERSIONLIE;
|
|
}
|
|
|
|
break;
|
|
|
|
case TEXT('x'): // NOTE: To pass command line parameters to the App. pass it in " " after
|
|
// -x . Eg. apcompat -x"yyy.exe " ..Command line params..blah..blah..
|
|
|
|
SkipBlanks(pNextWord);
|
|
AppName = (TCHAR*)malloc(sizeof(TCHAR) * ( lstrlen(pCh) + 1) );
|
|
if(AppName != NULL)
|
|
lstrcpy(AppName,pCh);
|
|
|
|
break;
|
|
|
|
case TEXT('h'):
|
|
default :
|
|
|
|
GetHelpPath(szDirectoryPath);
|
|
hHelpWnd = HtmlHelp(GetDesktopWindow(), szDirectoryPath, HH_DISPLAY_TOPIC,
|
|
(DWORD_PTR)IDHH_CMDSYNTAX );
|
|
// Loop till the Help window exists.
|
|
while(IsWindow(hHelpWnd) )
|
|
Sleep(200);
|
|
|
|
if(AppName)
|
|
free(AppName);
|
|
return 0;
|
|
|
|
} // End switch
|
|
|
|
if(fEnd == FALSE)
|
|
pCh = pNextWord+1;
|
|
|
|
}while( FALSE == fEnd);
|
|
}
|
|
|
|
if((AppName == NULL) ||
|
|
lstrlen(AppName) == 0)/* Return if no Application name given */
|
|
{
|
|
if(FALSE == fHelpDisplay ){
|
|
GetHelpPath(szDirectoryPath);
|
|
hHelpWnd = HtmlHelp(NULL, szDirectoryPath, HH_DISPLAY_TOPIC,
|
|
(DWORD_PTR)IDHH_CMDSYNTAX );
|
|
while(IsWindow(hHelpWnd) )
|
|
Sleep(200);
|
|
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
memset(szCommandLine, 0, MAX_PATH);
|
|
GetFileExtension(AppName,szTitle,szCommandLine);
|
|
GetDirectoryPath(AppName, szCurDir);
|
|
SetCurrentDirectory(szCurDir);
|
|
|
|
if(fDisableHeapLookAside)
|
|
{
|
|
SetRegistryVal(szTitle,TEXT("DisableHeapLookAside"), TEXT("1"),REG_SZ );
|
|
}
|
|
else{
|
|
CheckAndDeleteKey(szTitle,FALSE);
|
|
} //End Else
|
|
|
|
if(fSetTemp){
|
|
SetTempPath();
|
|
}
|
|
|
|
if(!fKeepRegistrySetting)
|
|
g_fNotPermanent = TRUE;
|
|
if(g_fAppCompatGoo)
|
|
MakeAppCompatGoo(AppName,&AppCompatFlag,VersionNum);
|
|
|
|
if(SetEnvironmentVariable(TEXT("_COMPAT_VER_NNN"), pVersionVal[VersionNum]) == 0)
|
|
{
|
|
if( ERROR_ENVVAR_NOT_FOUND != GetLastError() )
|
|
DetailError( GetLastError() );
|
|
}
|
|
|
|
// Execute the application.
|
|
if(fKeepRegistrySetting)
|
|
ExecuteApp(NULL, AppName,szTitle,szCommandLine,FALSE);
|
|
else{
|
|
ExecuteApp(NULL, AppName,szTitle,szCommandLine,TRUE);
|
|
}
|
|
|
|
if(AppName)
|
|
free(AppName);
|
|
if(pStr)
|
|
free(pStr);
|
|
|
|
GlobalFree(g_lpPrevRegSettings);
|
|
return 0;
|
|
}
|
|
|
|
/* Create a MODAL Dialog */
|
|
DialogBox(hInstance, TEXT("DialogProc"),(HWND)NULL, DialogProc);
|
|
|
|
while(GetMessage(&msg, NULL, 0, 0))
|
|
{
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
}
|
|
return (int)msg.wParam ;
|
|
}
|
|
|
|
|
|
/* Dialog procedure... */
|
|
INT_PTR CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
int dCharCnt,indx,length;
|
|
TCHAR EditCtrlBuf[_MAX_PATH];
|
|
static int BufCnt;
|
|
TCHAR FileBuf[_MAX_PATH];
|
|
TCHAR FileTitle[_MAX_PATH],szCommandLine[MAX_PATH];
|
|
TCHAR szDirectoryPath[_MAX_PATH];
|
|
static HANDLE hEditCtrl;
|
|
static HANDLE hRadioBtn;
|
|
static HANDLE hBrowseBtn;
|
|
static HANDLE hLaunchBtn,hCheck1,hCheck2,hCheck3,hCheck4,hDCOMFTM,hOldPathName;
|
|
static const TCHAR* pEnvVal = NULL;
|
|
OPENFILENAME ofn;
|
|
HKEY hKey;
|
|
TCHAR szTitle[MAXTITLE],szKeyName[MAXKEY],szSubKey[MAXKEY];
|
|
TCHAR szFileName[_MAX_PATH];
|
|
DWORD dwEnvSetError;
|
|
static LARGE_INTEGER AppCompatFlag ;
|
|
static UINT uOsVerID = IDD_NONE;
|
|
static BOOL fOfnFlag = FALSE;
|
|
static TCHAR szCurDir[MAX_PATH];
|
|
|
|
switch(uMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
|
|
hEditCtrl = GetDlgItem(hwndDlg, IDD_APPEDIT); /* To be used when reading and
|
|
writing from the EDIT control */
|
|
hRadioBtn = GetDlgItem(hwndDlg, IDD_NONE);
|
|
SendMessage(hRadioBtn , BM_SETCHECK, 1, 0L);
|
|
SetFocus(hEditCtrl);
|
|
return TRUE;
|
|
|
|
case WM_CLOSE:
|
|
EndDialog(hwndDlg, 0);
|
|
break;
|
|
|
|
case WM_DESTROY:
|
|
PostQuitMessage(0);
|
|
return 0;
|
|
|
|
case WM_COMMAND:
|
|
|
|
if(FALSE==fOfnFlag){
|
|
if( LOWORD(wParam) == IDD_APPEDIT ){
|
|
if( HIWORD(wParam) == EN_UPDATE){
|
|
GetWindowText(hEditCtrl,EditCtrlBuf, _MAX_PATH);
|
|
/* Check whether the *.exe is present in Registry */
|
|
GetFileExtension(EditCtrlBuf,szTitle,szCommandLine);
|
|
if(CheckAndDeleteKey(szTitle,TRUE) == ERROR_SUCCESS){
|
|
/* The executable already has an entry
|
|
in the registry */
|
|
|
|
hCheck1 = GetDlgItem(hwndDlg, IDD_CHECK1);
|
|
SendMessage(hCheck1,BM_SETCHECK, 1, 0L);
|
|
}
|
|
else{ // Uncheck if previously checked only.
|
|
if( SendMessage(hCheck1,BM_GETCHECK, 0, 0L) )
|
|
SendMessage(hCheck1,BM_SETCHECK, 0, 0L);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
switch(wParam)
|
|
{
|
|
case IDCANCEL:
|
|
EndDialog(hwndDlg, 0);
|
|
break;
|
|
|
|
case IDD_HELP:
|
|
GetHelpPath(szDirectoryPath);
|
|
lstrcat(szDirectoryPath, TEXT("::/topics/appcomp.htm>mainwin") );
|
|
HtmlHelp(GetDesktopWindow(), szDirectoryPath, HH_DISPLAY_TOPIC,(DWORD_PTR) NULL);
|
|
break;
|
|
/*
|
|
For the Browse button, Open the FileOpen dialog and get the
|
|
application path.
|
|
Display the path in the Edit box.
|
|
|
|
*/
|
|
case IDD_BROWSE:
|
|
GetDlgItemText(hwndDlg, IDD_APPEDIT, EditCtrlBuf, _MAX_PATH);
|
|
memset(&ofn, 0, sizeof(OPENFILENAME) );
|
|
FileBuf[0] = TEXT('\0');
|
|
/* Initialize the Ofn structure */
|
|
ofn.lStructSize = sizeof (OPENFILENAME) ;
|
|
ofn.hwndOwner = hwndDlg;
|
|
ofn.lpstrFilter = szFilter;
|
|
ofn.lpstrFile = FileBuf;
|
|
ofn.nMaxFile = _MAX_PATH ;
|
|
ofn.lpstrInitialDir= EditCtrlBuf;
|
|
ofn.Flags = OFN_PATHMUSTEXIST |
|
|
OFN_FILEMUSTEXIST;
|
|
|
|
if( GetOpenFileName (&ofn) != 0){
|
|
/* Got the file name ...*/
|
|
// To put a '"' before and after what is typed...
|
|
if( (*FileBuf) != TEXT('\"') ){
|
|
memset(EditCtrlBuf, 0, MAX_PATH);
|
|
*(EditCtrlBuf) = TEXT('\"');
|
|
lstrcat(EditCtrlBuf, FileBuf);
|
|
lstrcat(EditCtrlBuf, TEXT("\""));
|
|
SetWindowText(hEditCtrl,EditCtrlBuf);
|
|
}
|
|
// Set the flag so that anything entered after this will not be taken over by
|
|
// the Edit control input...
|
|
fOfnFlag = TRUE;
|
|
/* Check whether the *.exe is present in Registry */
|
|
|
|
GetFileExtension(FileBuf,szTitle,szCommandLine);
|
|
if(CheckAndDeleteKey(szTitle,TRUE) == ERROR_SUCCESS){
|
|
/* The executable already has an entry
|
|
in the registry */
|
|
hCheck1 = GetDlgItem(hwndDlg, IDD_CHECK1);
|
|
SendMessage(hCheck1,BM_SETCHECK, 1, 0L);
|
|
}
|
|
/* At this pt. set focus on the 'LAUNCH' button */
|
|
hLaunchBtn = GetDlgItem(hwndDlg, IDD_LAUNCH);
|
|
SetFocus(hLaunchBtn);
|
|
}
|
|
|
|
break;
|
|
|
|
/*
|
|
When any of the Radio buttons in the OS version group is checked,
|
|
get the version ID and store the corresponding COMPAT flag.. in the
|
|
local variable.
|
|
*/
|
|
case IDD_WIN95:
|
|
case IDD_WIN98:
|
|
case IDD_WINNT43:
|
|
case IDD_WINNT44:
|
|
case IDD_WINNT45:
|
|
case IDD_NONE:
|
|
if(wParam != IDD_NONE){
|
|
g_fAppCompatGoo = TRUE;
|
|
AppCompatFlag.LowPart |= KACF_VERSIONLIE;
|
|
}
|
|
uOsVerID = (UINT)(wParam - FIRSTBUTTON);
|
|
CheckRadioButton(hwndDlg,(int)FIRSTBUTTON,(int)LASTBUTTON,(int)wParam);
|
|
pEnvVal = pVersionVal[wParam - FIRSTBUTTON];
|
|
break;
|
|
|
|
case IDD_LAUNCH:
|
|
dCharCnt = GetWindowTextLength( hEditCtrl );
|
|
if(dCharCnt > 0){
|
|
/*
|
|
Go in only if something is present in the
|
|
EDIT box
|
|
*/
|
|
|
|
if(GetWindowText(hEditCtrl, EditCtrlBuf, dCharCnt + 1) == 0){
|
|
DetailError(GetLastError() );
|
|
}
|
|
else{ /* Launch the APP using ShellExecuteEx */
|
|
memset(szCommandLine, 0, MAX_PATH);
|
|
GetFileExtension(EditCtrlBuf,szTitle,szCommandLine);
|
|
GetDirectoryPath(EditCtrlBuf, szCurDir);
|
|
SetCurrentDirectory(szCurDir);
|
|
|
|
hCheck1 = GetDlgItem(hwndDlg, IDD_CHECK1);
|
|
if( SendMessage(hCheck1, BM_GETSTATE, 0, 0L)){
|
|
/* The checkbox has been checked
|
|
- DisableHeapLookAside */
|
|
|
|
SetRegistryVal(szTitle, TEXT("DisableHeapLookAside"), TEXT("1"),REG_SZ );
|
|
}
|
|
else{
|
|
// If it is not thru the BROWSE button...user has got
|
|
// here by typing the path in the Edit Ctrl...
|
|
|
|
CheckAndDeleteKey(szTitle,FALSE);
|
|
}
|
|
|
|
hCheck2 = GetDlgItem(hwndDlg, IDD_CHECK2);
|
|
if( SendMessage(hCheck2, BM_GETSTATE, 0, 0L)){
|
|
// Short Temp path.
|
|
g_fAppCompatGoo = TRUE;
|
|
AppCompatFlag.LowPart |=KACF_GETTEMPPATH;
|
|
SetTempPath();
|
|
}
|
|
|
|
hCheck4 = GetDlgItem(hwndDlg, IDD_CHECK4);
|
|
if( SendMessage(hCheck4, BM_GETSTATE, 0, 0L) ){
|
|
g_fAppCompatGoo = TRUE;
|
|
AppCompatFlag.LowPart |= KACF_GETDISKFREESPACE;
|
|
}
|
|
#ifdef EXTRA_APP_COMPAT
|
|
hDCOMFTM = GetDlgItem(hwndDlg, IDD_DCOMFTM);
|
|
if( SendMessage(hDCOMFTM, BM_GETSTATE, 0, 0L) ){
|
|
g_fAppCompatGoo = TRUE;
|
|
AppCompatFlag.LowPart |= KACF_FTMFROMCURRENTAPT;
|
|
}
|
|
|
|
hOldPathName = GetDlgItem(hwndDlg, IDD_OLDPATH);
|
|
if( SendMessage(hOldPathName, BM_GETSTATE, 0, 0L) ){
|
|
g_fAppCompatGoo = TRUE;
|
|
AppCompatFlag.LowPart |= KACF_OLDGETSHORTPATHNAME;
|
|
}
|
|
#endif
|
|
|
|
hCheck3 = GetDlgItem(hwndDlg, IDD_CHECK3);
|
|
if( SendMessage(hCheck3, BM_GETSTATE, 0, 0L) == 0)
|
|
g_fNotPermanent = TRUE;
|
|
|
|
if(g_fAppCompatGoo)
|
|
MakeAppCompatGoo(EditCtrlBuf,&AppCompatFlag,uOsVerID);
|
|
|
|
/* Set the ENVIRONMENT Variable "_COMPAT_VER_NNN"
|
|
flag with the version checked before calling
|
|
ShellExecuteEx()
|
|
*/
|
|
if(SetEnvironmentVariable(TEXT("_COMPAT_VER_NNN"), pEnvVal) == 0){
|
|
dwEnvSetError = GetLastError();
|
|
if( ERROR_ENVVAR_NOT_FOUND != dwEnvSetError )
|
|
DetailError( GetLastError() );
|
|
}
|
|
|
|
|
|
if( g_fNotPermanent){
|
|
ExecuteApp(hwndDlg, EditCtrlBuf,szTitle,szCommandLine, TRUE);
|
|
}
|
|
else{
|
|
ExecuteApp(hwndDlg, EditCtrlBuf,szTitle,szCommandLine, FALSE);
|
|
}
|
|
EndDialog(hwndDlg, 0);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case IDD_CLOSE:
|
|
EndDialog(hwndDlg, 0);
|
|
}
|
|
|
|
GlobalFree(g_lpPrevRegSettings);
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|