/*

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



BOOL 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,
                               (DLGPROC)DialogProc);

    while(GetMessage(&msg, NULL, 0, 0))
    {
         TranslateMessage(&msg);
         DispatchMessage(&msg);
    }
  return (int)msg.wParam ;
}


/* Dialog procedure... */
BOOL 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;
}