browse.c
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 43k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. //
  2. //  Browse.C
  3. //
  4. //  Copyright (C) Microsoft, 1994,1995 All Rights Reserved.
  5. //
  6. //  History:
  7. //  ral 5/23/94 - First pass
  8. //  3/20/95  [stevecat] - NT port & real clean up, unicode, etc.
  9. //
  10. //
  11. #include "priv.h"
  12. #include "appwiz.h"
  13. #include "util.h"
  14. #ifdef WINNT
  15. #include <uastrfnc.h>
  16. #endif
  17. #ifdef WINNT
  18. #ifndef DOWNLEVEL_PLATFORM
  19. #include <tsappcmp.h>       // for TermsrvAppInstallMode
  20. #endif // DOWNLEVEL_PLATFORM
  21. #endif // WINNT
  22. // Copied from shelldllole2dup.h
  23. #define GUIDSTR_MAX (1+ 8 + 1 + 4 + 1 + 4 + 1 + 4 + 1 + 12 + 1 + 1)
  24. //
  25. //  Initialize the browse property sheet.  Limit the size of the edit control.
  26. //
  27. void BrowseInitPropSheet(HWND hDlg, LPARAM lParam)
  28. {
  29.     LPWIZDATA lpwd = InitWizSheet(hDlg, lParam, 0);
  30.     Edit_LimitText(GetDlgItem(hDlg, IDC_COMMAND), ARRAYSIZE(lpwd->szExeName)-1);
  31. #ifndef DOWNLEVEL_PLATFORM
  32.     if (FAILED(SHAutoComplete(GetDlgItem(hDlg, IDC_COMMAND), 0)))
  33.     {
  34.         TraceMsg(TF_WARNING, "WARNING: Create Shortcut wizard won't AutoComplete because: 1) bad registry, 2) bad OleInit, or 3) Out of memory.");
  35.     }
  36. #endif //DOWNLEVEL_PLATFORM
  37. }
  38. //
  39. //  Sets the appropriate wizard buttons.  If there's any text in the
  40. //  edit control then Next is enabled.  Otherwise, Next and Back are both
  41. //  grey.
  42. //
  43. void SetBrowseButtons(LPWIZDATA lpwd)
  44. {
  45.     BOOL fIsText = GetWindowTextLength(GetDlgItem(lpwd->hwnd, IDC_COMMAND)) > 0;
  46.     BOOL fIsSetup = (lpwd->dwFlags & WDFLAG_SETUPWIZ);
  47.     int iBtns = fIsSetup ? PSWIZB_BACK : 0;
  48.     if (fIsSetup)
  49.     {
  50. #ifndef DOWNLEVEL_PLATFORM
  51. #ifdef WINNT       
  52.         // Are we running Terminal Service? Is this user an Admin?
  53.         if (IsTerminalServicesRunning() && IsUserAnAdmin())
  54.         {
  55.             lpwd->bTermSrvAndAdmin = TRUE;
  56.             iBtns |= fIsText ? PSWIZB_NEXT : PSWIZB_DISABLEDFINISH;
  57.         }
  58.         else
  59. #endif // WINNT
  60. #endif // DOWNLEVEL_PLATFORM
  61.             iBtns |= fIsText ? PSWIZB_FINISH : PSWIZB_DISABLEDFINISH;
  62.     }
  63.     else
  64.     {
  65.         if (fIsText)
  66.         {
  67.             iBtns |= PSWIZB_NEXT;
  68.         }
  69.     }
  70.     PropSheet_SetWizButtons(GetParent(lpwd->hwnd), iBtns);
  71. }
  72. //
  73. //  NOTES: 1) This function assumes that lpwd->hwnd has already been set to
  74. //           the dialogs hwnd.  2) This function is called from NextPushed
  75. //           if the application specified can not be found.
  76. //
  77. //  BrowseSetActive enables the next button and sets the focus to the edit
  78. //  control by posting a POKEFOCUS message.
  79. //
  80. void BrowseSetActive(LPWIZDATA lpwd)
  81. {
  82.     //
  83.     // NOTE: We re-use the szProgDesc string since it will always be reset
  84.     //       when this page is activated.  Use it to construct a command line.
  85.     //
  86.     #define   szCmdLine lpwd->szProgDesc
  87.     lstrcpy(szCmdLine, lpwd->szExeName);
  88.     PathQuoteSpaces(szCmdLine);
  89.     if (lpwd->szParams[0] != 0)
  90.     {
  91.         lstrcat(szCmdLine, TEXT(" "));
  92.         lstrcat(szCmdLine, lpwd->szParams);
  93.     }
  94.     Edit_SetText(GetDlgItem(lpwd->hwnd, IDC_COMMAND), szCmdLine);
  95.     if (lpwd->dwFlags & WDFLAG_SETUPWIZ)
  96.     {
  97.         int   iHaveHeader = IsTerminalServicesRunning() ? IDS_TSHAVESETUPPRG : IDS_HAVESETUPPRG;
  98.         int   iHeader = szCmdLine[0] != 0 ? iHaveHeader : IDS_NOSETUPPRG;
  99.         TCHAR szInstruct[MAX_PATH];
  100.         LoadString(g_hinst, iHeader, szInstruct, ARRAYSIZE(szInstruct));
  101.         Static_SetText(GetDlgItem(lpwd->hwnd, IDC_SETUPMSG), szInstruct);
  102.     }
  103.     SetBrowseButtons(lpwd);
  104.     PostMessage(lpwd->hwnd, WMPRIV_POKEFOCUS, 0, 0);
  105.     szCmdLine[0] = 0;            // Reset progdesc to empty string
  106.     #undef szCmdLine
  107. }
  108. //
  109. //  Returns TRUE if able to get properties for szExeName from PifMgr.  The
  110. //  program properties will be read into lpwd->PropPrg.
  111. //
  112. BOOL ReadPifProps(LPWIZDATA lpwd)
  113. {
  114.     HANDLE hPifProp;
  115.     LPTSTR lpszName = (lpwd->dwFlags & WDFLAG_EXPSZ) ? lpwd->szExpExeName : lpwd->szExeName;
  116.     hPifProp = PifMgr_OpenProperties(lpszName, NULL, 0, OPENPROPS_INHIBITPIF);
  117.     WIZERRORIF((!hPifProp), TEXT("Unable to open properties for DOS exe."))
  118.     if (hPifProp == 0)
  119.         return(FALSE);
  120.     PifMgr_GetProperties(hPifProp, (LPSTR)GROUP_PRG, &(lpwd->PropPrg),
  121.                          sizeof(lpwd->PropPrg), GETPROPS_NONE);
  122.     PifMgr_CloseProperties(hPifProp, CLOSEPROPS_DISCARD);
  123.     return(TRUE);
  124. }
  125. //
  126. //  Returns TRUE if lpwd->szExeName points to a valid exe type.  It also sets
  127. //  the appropriate flags, such as APPKNOWN and DOSAPP in the wizdata structure
  128. //  if the exe is valid.
  129. //
  130. void DetermineExeType(LPWIZDATA lpwd)
  131. {
  132.     DWORD   dwExeType;
  133.     LPTSTR  lpszName = (lpwd->dwFlags & WDFLAG_EXPSZ) ? lpwd->szExpExeName : lpwd->szExeName;
  134.     lpwd->dwFlags &= ~(WDFLAG_APPKNOWN | WDFLAG_DOSAPP | WDFLAG_SINGLEAPP);
  135.     dwExeType = (DWORD)SHGetFileInfo(lpszName, 0, NULL, 0, SHGFI_EXETYPE);
  136.     if (LOWORD(dwExeType) != ('M' | ('Z' << 8)))
  137.     {
  138.         lpwd->dwFlags |= WDFLAG_APPKNOWN;
  139.         if (lstrcmpi(PathFindExtension(lpszName), c_szPIF) == 0)
  140.         {
  141.             lpwd->dwFlags |= WDFLAG_DOSAPP;
  142.         }
  143.     }
  144.     else
  145.     {
  146.         lpwd->dwFlags |= WDFLAG_DOSAPP;
  147.         if (ReadPifProps(lpwd))
  148.         {
  149.             if ((lpwd->PropPrg.flPrgInit & PRGINIT_INFSETTINGS) ||
  150.                 ((lpwd->PropPrg.flPrgInit &
  151.                      (PRGINIT_NOPIF | PRGINIT_DEFAULTPIF)) == 0))
  152.             {
  153.                 lpwd->dwFlags |= WDFLAG_APPKNOWN;
  154.                 if (lpwd->PropPrg.flPrgInit & PRGINIT_REALMODE)
  155.                 {
  156.                     lpwd->dwFlags |= WDFLAG_SINGLEAPP;
  157.                 }
  158.             }
  159.         }
  160.     }
  161. }
  162. //
  163. //  Removes the filename extension (if any) from the string.
  164. //
  165. void StripExt(LPTSTR lpsz)
  166. {
  167.     LPTSTR pExt = PathFindExtension(lpsz);
  168.     if (*pExt)
  169.         *pExt = 0;    // null out the "."
  170. }
  171. //
  172. //  Sets the working directory as appropriate for the file type.
  173. //
  174. void FindWorkingDir(LPWIZDATA lpwd)
  175. {
  176.     LPTSTR lpszName = (lpwd->dwFlags & WDFLAG_EXPSZ) ? lpwd->szExpExeName : lpwd->szExeName;
  177. #ifdef WINNT
  178.     TCHAR szWindir[ MAX_PATH ];
  179.     DWORD dwLen;
  180. #endif
  181.     if (PathIsUNC(lpszName) || PathIsDirectory(lpszName))
  182.     {
  183.         lpwd->szWorkingDir[0] = 0;
  184.     }
  185.     else
  186.     {
  187.         lstrcpy(lpwd->szWorkingDir, lpszName);
  188.         PathRemoveFileSpec(lpwd->szWorkingDir);
  189.     }
  190. #ifdef WINNT
  191.     //
  192.     // Okay, at this point we should have the absolute path for the
  193.     // working directory of the link.  On NT, if the working dir happens to be for
  194.     // something in the %Windir% directory (or a subdir of %windir%),
  195.     // then store the path as %windir%blahblahblah instead of as an
  196.     // absolute path.  This will help with interoperability of shortcuts
  197.     // across different machines, etc.  But only do this for shortcuts that
  198.     // are already marked as having expandable env strings...
  199.     //
  200.     if (lpwd->dwFlags & WDFLAG_EXPSZ)
  201.     {
  202.         dwLen = ExpandEnvironmentStrings( TEXT("%windir%"),
  203.                                           szWindir,
  204.                                           ARRAYSIZE(szWindir)
  205.                                          );
  206.         if (dwLen &&
  207.             dwLen < ARRAYSIZE(szWindir) &&
  208.             lstrlen(szWindir) <= lstrlen(lpwd->szWorkingDir)
  209.            )
  210.         {
  211.             //
  212.             // we use dwLen-1 because dwLen includes the '' character
  213.             //
  214.             if (CompareString( LOCALE_SYSTEM_DEFAULT,
  215.                                NORM_IGNORECASE,
  216.                                szWindir, dwLen-1 ,
  217.                                lpwd->szWorkingDir, dwLen-1
  218.                               ) == 2)
  219.             {
  220.                 TCHAR szWorkingDir[ MAX_PATH ];
  221.                 //
  222.                 // We should substitute the env variable for the
  223.                 // actual string here...
  224.                 //
  225.                 ualstrcpy( szWorkingDir, lpwd->szWorkingDir );
  226.                 ualstrcpy( lpwd->szWorkingDir, TEXT("%windir%") );
  227.                 // 8 == lstrlen("%windir%")
  228.                 ualstrcpy( lpwd->szWorkingDir + 12, szWorkingDir+dwLen-1 );
  229.             }
  230.         }
  231.     }
  232. #endif // winnt
  233. }
  234. #ifndef NO_NEW_SHORTCUT_HOOK
  235. //
  236. // Returns:
  237. //    Hook result or error.
  238. //
  239. // S_OK:
  240. //    *pnshhk is the INewShortcutHook of the object to use to save the new Shortcut.
  241. //    szProgDesc[] and szExt[] are filled in.
  242. //    szExeName[] may be translated.
  243. // otherwise:
  244. //    *pnshhk is NULL.
  245. //    szProgDesc[] and szExt[] are empty strings.
  246. //
  247. HRESULT QueryNewLinkHandler(LPWIZDATA lpwd, LPCLSID pclsidHook)
  248. {
  249.    HRESULT   hr;
  250.    IUnknown *punk;
  251.    LPTSTR lpszName = (lpwd->dwFlags & WDFLAG_EXPSZ) ? lpwd->szExpExeName : lpwd->szExeName;
  252.    lpwd->pnshhk = NULL;
  253. #ifdef UNICODE
  254.    lpwd->pnshhkA = NULL;
  255. #endif
  256.    *(lpwd->szProgDesc) = TEXT('');
  257.    *(lpwd->szExt) = TEXT('');
  258.    hr = CoCreateInstance(pclsidHook, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, &punk);
  259.    if (hr == S_OK)
  260.    {
  261.       INewShortcutHook *pnshhk;
  262.       hr = punk->lpVtbl->QueryInterface(punk, &IID_INewShortcutHook, &pnshhk);
  263.       if (hr == S_OK)
  264.       {
  265.          hr = pnshhk->lpVtbl->SetReferent(pnshhk, lpszName, lpwd->hwnd);
  266.          if (hr == S_OK)
  267.          {
  268.             hr = pnshhk->lpVtbl->SetFolder(pnshhk, lpwd->lpszFolder);
  269.             if (hr == S_OK)
  270.             {
  271.                hr = pnshhk->lpVtbl->GetName(pnshhk, lpwd->szProgDesc,
  272.                                             ARRAYSIZE(lpwd->szProgDesc));
  273.                if (hr == S_OK)
  274.                {
  275.                   hr = pnshhk->lpVtbl->GetExtension(pnshhk, lpwd->szExt,
  276.                                                     ARRAYSIZE(lpwd->szExt));
  277.                   if (hr == S_OK)
  278.                      hr = pnshhk->lpVtbl->GetReferent(pnshhk, lpszName,
  279.                                                       ARRAYSIZE(lpwd->szExeName));
  280.                }
  281.             }
  282.          }
  283.          if (hr == S_OK)
  284.             lpwd->pnshhk = pnshhk;
  285.          else
  286.             pnshhk->lpVtbl->Release(pnshhk);
  287.       }
  288. #ifdef UNICODE
  289.       else
  290.       {
  291.           INewShortcutHookA *pnshhkA;
  292.           hr = punk->lpVtbl->QueryInterface(punk, &IID_INewShortcutHookA, &pnshhkA);
  293.           if (hr == S_OK)
  294.           {
  295.              UINT   cFolderA = WideCharToMultiByte(CP_ACP,0,lpwd->lpszFolder,-1,NULL,0,0,0)+1;
  296.              LPSTR  lpszFolderA = (LPSTR)LocalAlloc(LPTR,cFolderA*SIZEOF(CHAR));
  297.              CHAR   szNameA[MAX_PATH];
  298.              CHAR   szProgDescA[MAX_PATH];
  299.              CHAR   szExtA[MAX_PATH];
  300.              WideCharToMultiByte(CP_ACP, 0,
  301.                                  lpszName, -1,
  302.                                  szNameA, ARRAYSIZE(szNameA),
  303.                                  0, 0);
  304.              WideCharToMultiByte(CP_ACP, 0,
  305.                                  lpwd->lpszFolder, -1,
  306.                                  lpszFolderA, cFolderA,
  307.                                  0, 0);
  308.              if (lpszFolderA != NULL)
  309.              {
  310.                  hr = pnshhkA->lpVtbl->SetReferent(pnshhkA, szNameA, lpwd->hwnd);
  311.                  if (hr == S_OK)
  312.                  {
  313.                     hr = pnshhkA->lpVtbl->SetFolder(pnshhkA, lpszFolderA);
  314.                     if (hr == S_OK)
  315.                     {
  316.                        hr = pnshhkA->lpVtbl->GetName(pnshhkA, szProgDescA,
  317.                                                     ARRAYSIZE(szProgDescA));
  318.                        if (hr == S_OK)
  319.                        {
  320.                           MultiByteToWideChar(CP_ACP, 0,
  321.                                               szProgDescA, -1,
  322.                                               lpwd->szProgDesc, ARRAYSIZE(lpwd->szProgDesc));
  323.                           hr = pnshhkA->lpVtbl->GetExtension(pnshhkA, szExtA,
  324.                                                             ARRAYSIZE(szExtA));
  325.                           if (hr == S_OK)
  326.                           {
  327.                              MultiByteToWideChar(CP_ACP, 0,
  328.                                                  szExtA, -1,
  329.                                                  lpwd->szExt, ARRAYSIZE(lpwd->szExt));
  330.                              hr = pnshhkA->lpVtbl->GetReferent(pnshhkA, szNameA,
  331.                                                               ARRAYSIZE(szNameA));
  332.                              MultiByteToWideChar(CP_ACP, 0,
  333.                                                  szExtA, -1,
  334.                                                  lpszName, ARRAYSIZE(lpwd->szExeName));
  335.                           }
  336.                        }
  337.                     }
  338.                  }
  339.                  if (hr == S_OK)
  340.                     lpwd->pnshhkA = pnshhkA;
  341.                  else
  342.                     pnshhkA->lpVtbl->Release(pnshhkA);
  343.                  if (lpszFolderA)
  344.                     LocalFree(lpszFolderA);
  345.              }
  346.              else
  347.                 hr = E_OUTOFMEMORY;
  348.           }
  349.       }
  350. #endif
  351.       punk->lpVtbl->Release(punk);
  352.    }
  353.    return(hr);
  354. }
  355. const TCHAR c_szNewLinkHandlers[] = REGSTR_PATH_EXPLORER TEXT("\NewShortcutHandlers");
  356. //
  357. // Sets lpwd->pnshhk to NULL for CLSID_ShellLink (default) or to the
  358. // INewShortcutHook of the object to be used.
  359. //
  360. // If lpwd->pnshhk is returned non-NULL, szProgDesc[] and szExt[] are also
  361. // filled in.
  362. //
  363. void DetermineLinkHandler(LPWIZDATA lpwd)
  364. {
  365.    HKEY hkeyHooks;
  366.    // Lose any previously saved external new Shortcut handler.
  367.    if (lpwd->pnshhk)
  368.    {
  369.       lpwd->pnshhk->lpVtbl->Release(lpwd->pnshhk);
  370.       lpwd->pnshhk = NULL;
  371.    }
  372. #ifdef UNICODE
  373.    if (lpwd->pnshhkA)
  374.    {
  375.       lpwd->pnshhkA->lpVtbl->Release(lpwd->pnshhkA);
  376.       lpwd->pnshhkA = NULL;
  377.    }
  378. #endif
  379.    //
  380.    // Enumerate the list of new link handlers.  Each new link handler is
  381.    // registered as a GUID value under c_szNewLinkHandlers.
  382.    //
  383.    if (RegOpenKey(HKEY_LOCAL_MACHINE, c_szNewLinkHandlers, &hkeyHooks)
  384.        == ERROR_SUCCESS)
  385.    {
  386.       DWORD dwiValue;
  387.       TCHAR szCLSID[GUIDSTR_MAX];
  388.       DWORD dwcbCLSIDLen;
  389.       //
  390.       // Invoke each hook.  A hook returns S_FALSE if it does not wish to
  391.       // handle the new link.  Stop if a hook returns S_OK.
  392.       //
  393.       for (dwcbCLSIDLen = ARRAYSIZE(szCLSID), dwiValue = 0;
  394.            RegEnumValue(hkeyHooks, dwiValue, szCLSID, &dwcbCLSIDLen, NULL,
  395.                         NULL, NULL, NULL) == ERROR_SUCCESS;
  396.            dwcbCLSIDLen = ARRAYSIZE(szCLSID), dwiValue++)
  397.       {
  398.          CLSID clsidHook;
  399.          if (SHCLSIDFromString(szCLSID, &clsidHook) == S_OK &&
  400.              QueryNewLinkHandler(lpwd, &clsidHook) == S_OK)
  401.             break;
  402.       }
  403.       RegCloseKey(hkeyHooks);
  404.    }
  405.    return;
  406. }
  407. #endif
  408. void _inline PathRemoveArgs(LPTSTR pszPath)
  409. {
  410.     LPTSTR pArgs = PathGetArgs(pszPath);
  411.     if (*pArgs)
  412.     {
  413.         *(pArgs - 1) = TEXT('');   // clobber the ' '
  414.     }
  415.     else
  416.     {
  417.         //
  418.         // Handle trailing space.
  419.         //
  420.         pArgs = CharPrev(pszPath, pArgs);
  421.         if (*pArgs == TEXT(' '))
  422.             *pArgs = TEXT('');
  423.     }
  424. }
  425. //
  426. //  Returns TRUE if it's OK to go to the next wizard dialog.
  427. //
  428. BOOL NextPushed(LPWIZDATA lpwd)
  429. {
  430.     GetDlgItemText(lpwd->hwnd, IDC_COMMAND, lpwd->szExeName, ARRAYSIZE(lpwd->szExeName));
  431.     // Is the string a path with spaces, without arguments, but isn't correctly
  432.     // quoted?  NT #d: >C:Program FilesWindows NTdialer.exe< is treated like
  433.     // "C:Program" with "FilesWindows NTdialer.exe" as args.
  434.     if (PathFileExists(lpwd->szExeName))
  435.     {
  436.         // Yes, so let's quote it so we don't treat the stuff after
  437.         // the space like args.
  438.         PathQuoteSpaces(lpwd->szExeName);
  439.     }
  440.     
  441.     PathRemoveBlanks(lpwd->szExeName);
  442.     if (lpwd->szExeName[0] != 0)
  443.     {
  444.         BOOL    bUNC;
  445.         LPTSTR  lpszTarget = NULL;
  446.         HCURSOR hcurOld  = SetCursor(LoadCursor(NULL, IDC_WAIT));
  447.         LPTSTR  lpszArgs = PathGetArgs(lpwd->szExeName);
  448.         lstrcpy(lpwd->szParams, lpszArgs);
  449.         if (*lpszArgs)
  450.         {
  451.             *(lpszArgs - 1) = 0;   // clobber the ' ' in the exe name field
  452.         }
  453.         ExpandEnvironmentStrings( lpwd->szExeName,
  454.                                   lpwd->szExpExeName,
  455.                                   ARRAYSIZE(lpwd->szExpExeName)
  456.                                  );
  457.         lpwd->szExpExeName[ MAX_PATH-1 ] = TEXT('');
  458.         if (lstrcmp(lpwd->szExeName, lpwd->szExpExeName))
  459.             lpwd->dwFlags |= WDFLAG_EXPSZ;
  460.         lpszTarget = (lpwd->dwFlags & WDFLAG_EXPSZ) ? lpwd->szExpExeName : lpwd->szExeName;
  461.         PathUnquoteSpaces(lpszTarget);
  462.         if (lpwd->dwFlags & WDFLAG_EXPSZ)
  463.             PathUnquoteSpaces(lpwd->szExeName);
  464.         lpwd->dwFlags &= ~WDFLAG_COPYLINK;
  465. #ifndef NO_NEW_SHORTCUT_HOOK
  466.         //
  467.         // Figure out who wants to handle this string as a link referent.
  468.         //
  469.         DetermineLinkHandler(lpwd);
  470.         if (lpwd->pnshhk)
  471.         {
  472.             //
  473.             // We are using an external link handler.  Skip file system
  474.             // validation.
  475.             //
  476.             lpwd->dwFlags |= WDFLAG_APPKNOWN;
  477.             SetCursor(hcurOld);
  478.             return(TRUE);
  479.         }
  480. #ifdef UNICODE
  481.         if (lpwd->pnshhkA)
  482.         {
  483.             //
  484.             // We are using an external link handler.  Skip file system
  485.             // validation.
  486.             //
  487.             lpwd->dwFlags |= WDFLAG_APPKNOWN;
  488.             SetCursor(hcurOld);
  489.             return(TRUE);
  490.         }
  491. #endif
  492. #endif
  493.         bUNC = PathIsUNC(lpszTarget);
  494.         if (bUNC && !SHValidateUNC(lpwd->hwnd, lpszTarget, FALSE))
  495.             goto Done;
  496.         //
  497.         //  If the user tries to make a link to A: and there's no disk
  498.         //  in the drive, PathResolve would fail.  So, for drive roots, we
  499.         //  don't try to resolve it.
  500.         //
  501.         if ((PathIsRoot(lpszTarget) && !bUNC &&
  502.              DriveType(DRIVEID(lpszTarget))) ||
  503.              PathResolve(lpszTarget, NULL,
  504.                          PRF_VERIFYEXISTS | PRF_TRYPROGRAMEXTENSIONS))
  505.         {
  506.             //
  507.             // If we found a PIF file then we'll try to convert it to the
  508.             // name of the file it points to.
  509.             //
  510.             if (lstrcmpi(PathFindExtension(lpszTarget), c_szPIF) == 0)
  511.             {
  512.                 if (!ReadPifProps(lpwd))
  513.                 {
  514.                     goto Done;
  515.                 }
  516. #ifdef UNICODE
  517.                 MultiByteToWideChar(CP_ACP, 0, lpwd->PropPrg.achCmdLine, -1,
  518.                                     lpszTarget, ARRAYSIZE(lpwd->szExeName));
  519. #else
  520.                 lstrcpy(lpszTarget, lpwd->PropPrg.achCmdLine);
  521. #endif // UNICODE
  522.                 PathRemoveArgs(lpszTarget);
  523.                 if (!PathResolve(lpszTarget, NULL,
  524.                                  PRF_VERIFYEXISTS | PRF_TRYPROGRAMEXTENSIONS))
  525.                 {
  526.                     goto Done;
  527.                 }
  528.             }
  529. #ifdef WINNT
  530.             //
  531.             // Okay, at this point we should have the absolute path for the
  532.             // target of the link.  On NT, if the target happens to be for
  533.             // something in the %Windir% directory (or a subdir of %Windir%),
  534.             // AND the user didn't type in an expandable path already, then
  535.             // store the path as %windir%blahblahblah instead of as an
  536.             // absolute path.  This will help with interoperability of shortcuts
  537.             // across different machines, etc.
  538.             //
  539.             if (!(lpwd->dwFlags & WDFLAG_EXPSZ))
  540.             {
  541.                 TCHAR szWindir[ MAX_PATH ];
  542.                 DWORD dwLen;
  543.                 //
  544.                 // What did the user type in?
  545.                 //
  546.                 GetDlgItemText(lpwd->hwnd, IDC_COMMAND, szWindir, ARRAYSIZE(szWindir));
  547.                 if (ualstrcmpi(szWindir, lpwd->szExeName)==0)
  548.                 {
  549.                     //
  550.                     // If we didn't change it, it means the user typed in an
  551.                     // exact path.  In that case, don't try to map anyting.
  552.                     //
  553.                     goto LinkToALinkCase;
  554.                 }
  555.                 dwLen = ExpandEnvironmentStrings( TEXT("%windir%"),
  556.                                                   szWindir,
  557.                                                   ARRAYSIZE(szWindir)
  558.                                                  );
  559.                 if (dwLen &&
  560.                     dwLen < ARRAYSIZE(szWindir) &&
  561.                     lstrlen(szWindir) <= lstrlen(lpszTarget)
  562.                    )
  563.                 {
  564.                     //
  565.                     // we use dwLen-1 because dwLen includes the '' character
  566.                     //
  567.                     if (CompareString( LOCALE_SYSTEM_DEFAULT,
  568.                                        NORM_IGNORECASE,
  569.                                        szWindir, dwLen-1 ,
  570.                                        lpszTarget, dwLen-1
  571.                                       ) == 2)
  572.                     {
  573.                         //
  574.                         // We should substitute the env variable for the
  575.                         // actual string here...
  576.                         //
  577.                         lstrcpy( lpwd->szExpExeName, lpwd->szExeName );
  578.                         lstrcpy( lpwd->szExeName, TEXT("%windir%") );
  579.                         // 8 == lstrlen("%windir%")
  580.                         ualstrcpy( lpwd->szExeName + 8, lpwd->szExpExeName+dwLen-1 );
  581.                         lpwd->dwFlags |= WDFLAG_EXPSZ;
  582.                         lpszTarget = lpwd->szExpExeName;
  583.                     }
  584.                 }
  585.             }
  586. #endif // winnt
  587. #ifdef WINNT
  588.             //
  589.             // Okay, at this point we should have the absolute path for the
  590.             // target of the link.  On NT, if the target happens to be for
  591.             // something in the %Windir% directory (or a subdir of %Windir%),
  592.             // AND the user didn't type in an expandable path already, then
  593.             // store the path as %windir%blahblahblah instead of as an
  594.             // absolute path.  This will help with interoperability of shortcuts
  595.             // across different machines, etc.
  596.             //
  597.             if (!(lpwd->dwFlags & WDFLAG_EXPSZ))
  598.             {
  599.                 TCHAR szWindir[ MAX_PATH ];
  600.                 DWORD dwLen;
  601.                 //
  602.                 // What did the user type in?
  603.                 //
  604.                 GetDlgItemText(lpwd->hwnd, IDC_COMMAND, szWindir, ARRAYSIZE(szWindir));
  605.                 if (ualstrcmpi(szWindir, lpwd->szExeName)==0)
  606.                 {
  607.                     //
  608.                     // If we didn't change it, it means the user typed in an
  609.                     // exact path.  In that case, don't try to map anyting.
  610.                     //
  611.                     goto LinkToALinkCase;
  612.                 }
  613.                 dwLen = ExpandEnvironmentStrings( TEXT("%windir%"),
  614.                                                   szWindir,
  615.                                                   ARRAYSIZE(szWindir)
  616.                                                  );
  617.                 if (dwLen &&
  618.                     dwLen < ARRAYSIZE(szWindir) &&
  619.                     lstrlen(szWindir) <= lstrlen(lpszTarget)
  620.                    )
  621.                 {
  622.                     //
  623.                     // we use dwLen-1 because dwLen includes the '' character
  624.                     //
  625.                     if (CompareString( LOCALE_SYSTEM_DEFAULT,
  626.                                        NORM_IGNORECASE,
  627.                                        szWindir, dwLen-1 ,
  628.                                        lpszTarget, dwLen-1
  629.                                       ) == 2)
  630.                     {
  631.                         //
  632.                         // We should substitute the env variable for the
  633.                         // actual string here...
  634.                         //
  635.                         lstrcpy( lpwd->szExpExeName, lpwd->szExeName );
  636.                         lstrcpy( lpwd->szExeName, TEXT("%windir%") );
  637.                         // 8 == lstrlen("%windir%")
  638.                         ualstrcpy( lpwd->szExeName + 8, lpwd->szExpExeName+dwLen-1 );
  639.                         lpwd->dwFlags |= WDFLAG_EXPSZ;
  640.                         lpszTarget = lpwd->szExpExeName;
  641.                     }
  642.                 }
  643.             }
  644. LinkToALinkCase:
  645. #endif // winnt
  646.             //
  647.             //  Really, really obscure case. The user creates "New Shortcut" and
  648.             //  tries to point it to itself. Don't allow it.  We'd be confused
  649.             //  later. Since it's so obscure, just give a generic error about
  650.             //  "Can't find this file"
  651.             //
  652.             if (!(lpwd->lpszOriginalName &&
  653.                   lstrcmpi(lpwd->lpszOriginalName, lpszTarget) == 0))
  654.             {
  655.                 DetermineExeType(lpwd);
  656.                 FindWorkingDir(lpwd);
  657.                 lpwd->szProgDesc[0] = 0;  // Reset description
  658.                                           // EVEN IF WE DON'T RECREATE IT HERE!
  659.                 if (lpwd->lpszFolder && lpwd->lpszFolder[0] != 0 &&
  660.                     !DetermineDefaultTitle(lpwd))
  661.                 {
  662.                     goto Done;
  663.                 }
  664.                 if (lpwd->dwFlags & WDFLAG_EXPSZ)
  665.                 {
  666.                     LPTSTR lpszExt = PathFindExtension( lpwd->szExeName );
  667.                     if (!(*lpszExt))
  668.                     {
  669.                         // do simple check to make sure there was a file name
  670.                         // at the end of the original entry.  we assume that
  671.                         // if we got this far, lpszExt points to the end of
  672.                         // the string pointed to by lpwd->szExeName, and that
  673.                         // lpwd->szExeName has at least one character in it.
  674.                         if (lpwd->szExeName &&
  675.                             (*lpwd->szExeName) &&
  676.                             (*(lpszExt-1)!=TEXT('%'))
  677.                             )
  678.                         {
  679.                             lstrcpy( lpszExt, PathFindExtension( lpszTarget ) );
  680.                         }
  681.                     }
  682.                 }
  683.                 SetCursor(hcurOld);
  684.                 return(TRUE);
  685.             }
  686.         }
  687. Done:
  688.         SetCursor(hcurOld);
  689.         ShellMessageBox(g_hinst, lpwd->hwnd, MAKEINTRESOURCE(IDS_BADPATHMSG), 0, MB_OK | MB_ICONEXCLAMATION, lpwd->szExeName);
  690.     }
  691.     BrowseSetActive(lpwd);
  692.     return(FALSE);
  693. }
  694. //
  695. //  Returns TRUE if it's OK to run the setup program.
  696. //
  697. BOOL SetupCleanupExePath(LPWIZDATA lpwd)
  698. {
  699.     BOOL fValidPrg = FALSE;
  700.     GetDlgItemText(lpwd->hwnd, IDC_COMMAND, lpwd->szExeName, ARRAYSIZE(lpwd->szExeName));
  701.     PathRemoveBlanks(lpwd->szExeName);
  702.     if (lpwd->szExeName[0] != 0)
  703.     {
  704.         LPTSTR lpszTarget = NULL;
  705.         LPTSTR lpszArgs = NULL;
  706.         HCURSOR hcurOld = SetCursor(LoadCursor(NULL, IDC_WAIT));
  707.         ExpandEnvironmentStrings( lpwd->szExeName,
  708.                                   lpwd->szExpExeName,
  709.                                   ARRAYSIZE(lpwd->szExpExeName)
  710.                                  );
  711.         if (lstrcmp(lpwd->szExeName, lpwd->szExpExeName))
  712.             lpwd->dwFlags |= WDFLAG_EXPSZ;
  713.         lpszTarget = (lpwd->dwFlags & WDFLAG_EXPSZ) ? lpwd->szExpExeName : lpwd->szExeName;
  714.         lpszArgs = PathGetArgs(lpszTarget);
  715.         lstrcpy(lpwd->szParams, lpszArgs);
  716.         if (*lpszArgs)
  717.         {
  718.             *(lpszArgs - 1) = 0;   // clobber the ' ' in the exe name field
  719.         }
  720.         PathUnquoteSpaces(lpszTarget);
  721.         if (lpwd->dwFlags & WDFLAG_EXPSZ)
  722.             PathUnquoteSpaces(lpwd->szExeName);
  723.         if (PathResolve(lpszTarget, NULL,
  724.                         PRF_VERIFYEXISTS | PRF_TRYPROGRAMEXTENSIONS))
  725.         {
  726.             LPTSTR lpszExt = PathFindExtension( lpwd->szExeName );
  727.             fValidPrg = TRUE;
  728.             FindWorkingDir(lpwd);
  729.             if (lpwd->dwFlags & WDFLAG_EXPSZ)
  730.             {
  731.                 if (!(*lpszExt))
  732.                 {
  733.                     lstrcpy( lpszExt, PathFindExtension( lpszTarget ) );
  734.                 }
  735.             }
  736.             
  737.             if ((*lpszExt) && lpwd->bTermSrvAndAdmin && (!lstrcmpi(lpszExt, TEXT(".msi"))))
  738.                 lstrcat(lpwd->szParams, TEXT(" ALLUSERS=1"));
  739.             PathQuoteSpaces(lpwd->szExeName);
  740.         }
  741.         SetCursor(hcurOld);
  742.     }
  743.     if (!fValidPrg)
  744.     {
  745.         ShellMessageBox(g_hinst, lpwd->hwnd, MAKEINTRESOURCE(IDS_BADPATHMSG), 0, MB_OK | MB_ICONEXCLAMATION, lpwd->szExeName);
  746.         BrowseSetActive(lpwd);
  747.     }
  748.     return(fValidPrg);
  749. }
  750. BOOL DetermineDefaultTitle(LPWIZDATA lpwd)
  751. {
  752.     TCHAR   szFullName[MAX_PATH];
  753.     BOOL    fCopy;
  754.     LPTSTR  lpszName;
  755.     lpwd->dwFlags &= ~WDFLAG_COPYLINK;
  756.     if (lpwd->dwFlags & WDFLAG_EXPSZ)
  757.         lpszName = lpwd->szExpExeName;
  758.     else
  759.         lpszName = lpwd->szExeName;
  760.     if (!SHGetNewLinkInfo(lpszName, lpwd->lpszFolder, szFullName,
  761.                      &fCopy, 0))
  762.     {
  763.         //
  764.         // failure...
  765.         //
  766.         return(FALSE);
  767.     }
  768.     lpszName = PathFindFileName(szFullName);
  769.     StripExt(lpszName);
  770.     lstrcpyn(lpwd->szProgDesc, lpszName, ARRAYSIZE(lpwd->szProgDesc));
  771.     //
  772.     // We will never copy PIF files since they often do not contain
  773.     // the appropriate current directory.  This is becuase they are
  774.     // automatically created when you run a DOS application from the
  775.     // shell.
  776.     //
  777.     if ((lpwd->dwFlags & WDFLAG_DOSAPP) == 0)
  778.     {
  779.         if (fCopy)
  780.         {
  781.             lpwd->dwFlags |= WDFLAG_COPYLINK;
  782.         }
  783. #ifndef NO_NEW_SHORTCUT_HOOK
  784.         lstrcpy(lpwd->szExt, c_szLNK);
  785.     }
  786.     else
  787.     {
  788.         lstrcpy(lpwd->szExt, c_szPIF);
  789. #endif
  790.     }
  791.     return(TRUE);
  792. }
  793. //
  794. // paranoia: evaluate each time in case it is installed after ARP was first open, but
  795. //           before it is closed and re-opened
  796. //
  797. BOOL MSI_IsMSIAvailable()
  798. {
  799.     BOOL bAvailable = FALSE;
  800.     HINSTANCE hinst = LoadLibraryA("MSI.DLL");
  801.     
  802.     if (hinst)
  803.     {
  804.         bAvailable = TRUE;
  805.         FreeLibrary(hinst);
  806.     }
  807.     return bAvailable;
  808. }
  809. //
  810. //  Call the common dialog code for File Open
  811. //
  812. BOOL _inline BrowseForExe(HWND hwnd, LPTSTR pszName, DWORD cchName, LPCTSTR pszInitDir)
  813. {
  814.     TCHAR szExt[80];
  815.     TCHAR szFilter[200];
  816.     TCHAR szTitle[80];
  817.     TCHAR szBootDir[64];
  818.     //
  819.     // Must pass the buffer size to GetBootDir because that is what
  820.     // the RegQueryValueEx function expects - not count of chars.
  821.     //
  822.     if (!pszInitDir)
  823.     {
  824.         GetBootDir(szBootDir, ARRAYSIZE(szBootDir));
  825.     }
  826.     else
  827.     {
  828.         // we want to pass in an initial directory since GetFileNameFromBrowse
  829.         // try to determine an initial directory by doing a PathRemoveFileSpec
  830.         // on pszName.  If pszName is already a directory then the last directory
  831.         // is removed (even though it's not a file).  E.g.: "c:winnt" -> "c:"
  832.         lstrcpyn(szBootDir, pszInitDir, ARRAYSIZE(szBootDir));
  833.     }
  834.     if (MSI_IsMSIAvailable())
  835.         LoadAndStrip(IDS_BROWSEFILTERMSI, szFilter, ARRAYSIZE(szFilter));
  836.     else
  837.         LoadAndStrip(IDS_BROWSEFILTER, szFilter, ARRAYSIZE(szFilter));
  838.     LoadString(g_hinst, IDS_BROWSEEXT,    szExt,    ARRAYSIZE(szExt));
  839.     LoadString(g_hinst, IDS_BROWSETITLE,  szTitle,  ARRAYSIZE(szTitle));
  840.     // we need to set pszName to NULL or else GetFileNameFromBrowse will use it
  841.     // to find the initial directory even though we explicitly pass in an initial
  842.     // dir.
  843.     *pszName = 0;
  844.     return(GetFileNameFromBrowse(hwnd, pszName, cchName,
  845.                                  szBootDir, szExt, szFilter, szTitle));
  846. }
  847. //
  848. //  Use the common open dialog to browse for program. Used by SetupBrowseDlgProc
  849. //
  850. void BrowsePushed(LPWIZDATA lpwd)
  851. {
  852.     LPTSTR lpszName;
  853.     DWORD cchName = 0;
  854.     GetDlgItemText(lpwd->hwnd, IDC_COMMAND, lpwd->szExeName, ARRAYSIZE(lpwd->szExeName));
  855.     ExpandEnvironmentStrings( lpwd->szExeName, lpwd->szExpExeName, ARRAYSIZE(lpwd->szExpExeName) );
  856.     if (lstrcmp(lpwd->szExeName, lpwd->szExpExeName))
  857.         lpwd->dwFlags |= WDFLAG_EXPSZ;
  858.     if (lpwd->dwFlags & WDFLAG_EXPSZ)
  859.     {
  860.         lpszName = lpwd->szExpExeName;
  861.         cchName = ARRAYSIZE(lpwd->szExpExeName);
  862.     }
  863.     else
  864.     {
  865.         lpszName = lpwd->szExeName;
  866.         cchName = ARRAYSIZE(lpwd->szExeName);
  867.     }
  868.     if (BrowseForExe(lpwd->hwnd, lpszName, cchName, lpszName))
  869.     {
  870.         lpwd->szParams[0] = 0;
  871.         BrowseSetActive(lpwd);
  872.     }
  873. }
  874. int CALLBACK BrowseCallbackProc(
  875.     HWND hwnd, 
  876.     UINT uMsg, 
  877.     LPARAM lParam, 
  878.     LPARAM lpData
  879.     )
  880. {
  881.     LPITEMIDLIST pidlNavigate;
  882.     switch (uMsg)
  883.     {
  884.     case BFFM_INITIALIZED:
  885.         // Check if we should navigate to a folder on initialize
  886.         pidlNavigate = (LPITEMIDLIST) lpData;
  887.         if (pidlNavigate != NULL)
  888.         {
  889.             // Yes! We have a folder to navigate to; send the message
  890.             SendMessage(hwnd, BFFM_SETSELECTION, (WPARAM) FALSE, (LPARAM) pidlNavigate);
  891.         }
  892.         break;
  893.     }
  894.      
  895.     return 0;
  896. }
  897. // This implementation of 'Browse' uses SHBrowseForFolder to find a file or folder
  898. // for the shortcut wizard - used by BrowseDlgProc
  899. void BrowseForFileOrFolder(LPWIZDATA lpwd)
  900. {
  901.     TCHAR szBrowseTitle[256];
  902.     TCHAR szName[MAX_PATH];
  903.     BROWSEINFO bi = {0};
  904.     LPITEMIDLIST pidlSelected;
  905.     LPITEMIDLIST pidlStartBrowse;
  906.     IShellFolder* pdesktop;
  907.     // Try to start the browse at a location indicated by the typed-in command line,
  908.     // if possible
  909.     GetDlgItemText(lpwd->hwnd, IDC_COMMAND, lpwd->szExeName, ARRAYSIZE(lpwd->szExeName));
  910.     // ..Get the desktop folder
  911.     if (SUCCEEDED(SHGetDesktopFolder(&pdesktop)))
  912.     {
  913.         // ..Now try to parse the path the user entered into a pidl to start at
  914.         ULONG chEaten;
  915. #ifdef UNICODE
  916.         if (FAILED(pdesktop->lpVtbl->ParseDisplayName(pdesktop, lpwd->hwnd, NULL,
  917.             lpwd->szExeName, &chEaten, &pidlStartBrowse, NULL)))
  918. #else
  919.         WCHAR szTmp[MAX_PATH];
  920.         
  921.         SHAnsiToUnicode(lpwd->szExeName, szTmp, MAX_PATH);
  922.         if (FAILED(pdesktop->lpVtbl->ParseDisplayName(pdesktop, lpwd->hwnd, NULL,
  923.             szTmp, &chEaten, &pidlStartBrowse, NULL)))        
  924. #endif
  925.         {
  926.             // The path the user entered didn't make any sense
  927.             // pidlStartBrowse should already be NULL, but we want to make sure
  928.             pidlStartBrowse = NULL;
  929.         }
  930.         // Now we can continue and display the browse window
  931.         // Load the title string for the browse window
  932.         LoadString(g_hinst, IDS_FILEFOLDERBROWSE_TITLE, szBrowseTitle, ARRAYSIZE(szBrowseTitle));
  933.         // Note that bi = {0} for all other members except:
  934.         bi.hwndOwner = lpwd->hwnd;
  935.         bi.pszDisplayName = szName;
  936.         bi.lpszTitle = szBrowseTitle;
  937.         bi.ulFlags = BIF_BROWSEINCLUDEFILES | BIF_RETURNONLYFSDIRS;
  938.         // Ensure the pidl we want to start at is passed to the callback function
  939.         bi.lpfn = BrowseCallbackProc;
  940.         bi.lParam = (LPARAM) pidlStartBrowse;
  941.         pidlSelected = SHBrowseForFolder(&bi);
  942.         if (pidlSelected != NULL)
  943.         {
  944.             STRRET strret;
  945.             if (SUCCEEDED(pdesktop->lpVtbl->GetDisplayNameOf(pdesktop, pidlSelected, SHGDN_NORMAL | SHGDN_FORPARSING, &strret)))
  946.             {
  947.                 StrRetToStrN(lpwd->szExeName, ARRAYSIZE(lpwd->szExeName), &strret, pidlSelected);
  948.                 // Assume no parameters for this new file
  949.                 lpwd->szParams[0] = 0;
  950.                 
  951.                 // Populate the text box with the new file, etc.
  952.                 BrowseSetActive(lpwd);
  953.             }
  954.             // Free the pidl
  955.             ILFree(pidlSelected);
  956.         }
  957.         if (pidlStartBrowse != NULL)
  958.         {
  959.             ILFree(pidlStartBrowse);
  960.         }
  961.             
  962.         pdesktop->lpVtbl->Release(pdesktop);
  963.     }
  964.     else
  965.     {
  966.         // This really shouldn't happen; SHGetDesktopdesktop failed; out of memory?
  967.     }
  968. }
  969. //
  970. //  Main dialog procedure for first page of shortcut wizard.
  971. //
  972. //
  973. //  Note that there are now two BrowseDlgProcs, the one below and
  974. //  'SetupBrowseDlgProc'. This is because BrowseDlgProc now uses
  975. //  a different method for implementing the 'Browse' button and I
  976. //  wanted to do this without affecting the Setup Wizard which will
  977. //  now use SetupBrowseDlgProc. - dsheldon 6/16/98
  978. //
  979. BOOL_PTR CALLBACK BrowseDlgProc(HWND hDlg, UINT message , WPARAM wParam, LPARAM lParam)
  980. {
  981.     NMHDR FAR *lpnm;
  982.     LPPROPSHEETPAGE lpPropSheet = (LPPROPSHEETPAGE)(GetWindowLongPtr(hDlg, DWLP_USER));
  983.     LPWIZDATA lpwd;
  984.     if (lpPropSheet)
  985.     {
  986.         lpwd = (LPWIZDATA)lpPropSheet->lParam;
  987.     }
  988.     switch(message)
  989.     {
  990.         case WM_NOTIFY:
  991.             lpnm = (NMHDR FAR *)lParam;
  992.             switch(lpnm->code)
  993.             {
  994.                case PSN_SETACTIVE:
  995.                     lpwd->hwnd = hDlg;
  996.                     if (lpwd->dwFlags & WDFLAG_NOBROWSEPAGE)
  997.                     {
  998.                         SetDlgMsgResult(hDlg, WM_NOTIFY, -1);
  999.                     }
  1000.                     else
  1001.                     {
  1002.                         BrowseSetActive(lpwd);
  1003.                     }
  1004.                     break;
  1005.                case PSN_WIZNEXT:
  1006.                     if (!NextPushed(lpwd) ||
  1007.                         ((lpwd->dwFlags & WDFLAG_SETUPWIZ) && !SetupCleanupExePath(lpwd)))
  1008.                     {
  1009.                         SetDlgMsgResult(hDlg, WM_NOTIFY, -1);
  1010.                     }
  1011.                     break;
  1012.                case PSN_WIZFINISH:
  1013.                   {
  1014.                     BOOL ForceWx86;
  1015. #ifdef WX86
  1016.                     ForceWx86 = bWx86Enabled && bForceX86Env;
  1017. #else
  1018.                     ForceWx86 = FALSE;
  1019. #endif
  1020.                     if (!SetupCleanupExePath(lpwd) ||
  1021.                         !ExecSetupProg(lpwd, ForceWx86, TRUE))
  1022.                     {
  1023.                         BrowseSetActive(lpwd);
  1024.                         SetDlgMsgResult(hDlg, WM_NOTIFY, -1);
  1025.                     }
  1026.                     break;
  1027.                  }
  1028.                case PSN_RESET:
  1029.                     CleanUpWizData(lpwd);
  1030.                     break;
  1031.                default:
  1032.                   return FALSE;
  1033.             }
  1034.             break;
  1035.         case WM_INITDIALOG:
  1036.             BrowseInitPropSheet(hDlg, lParam);
  1037.             break;
  1038.         case WMPRIV_POKEFOCUS:
  1039.             {
  1040.             HWND hCmd = GetDlgItem(hDlg, IDC_COMMAND);
  1041.             SetFocus(hCmd);
  1042.             Edit_SetSel(hCmd, 0, -1);
  1043.             break;
  1044.             }
  1045.         case WM_DESTROY:
  1046.         case WM_HELP:
  1047.         case WM_CONTEXTMENU:
  1048.             break;
  1049.         case WM_COMMAND:
  1050.             switch (GET_WM_COMMAND_ID(wParam, lParam))
  1051.             {
  1052.                 case IDHELP:
  1053.                         break;
  1054.                 case IDC_COMMAND:
  1055.                     switch (GET_WM_COMMAND_CMD(wParam, lParam))
  1056.                     {
  1057.                         case EN_CHANGE:
  1058.                             SetBrowseButtons(lpwd);
  1059.                             break;
  1060.                     }
  1061.                     break;
  1062.                 case IDC_BROWSE:
  1063.                     BrowseForFileOrFolder(lpwd);
  1064.                     break;
  1065.             } // end of switch on WM_COMMAND
  1066.             break;
  1067.         default:
  1068.             return FALSE;
  1069.     } // end of switch on message
  1070.     return TRUE;
  1071. }  // BrowseDlgProc
  1072. BOOL_PTR CALLBACK SetupBrowseDlgProc(HWND hDlg, UINT message , WPARAM wParam, LPARAM lParam)
  1073. {
  1074.     NMHDR FAR *lpnm;
  1075.     LPPROPSHEETPAGE lpPropSheet = (LPPROPSHEETPAGE)(GetWindowLongPtr(hDlg, DWLP_USER));
  1076.     LPWIZDATA lpwd;
  1077.     if (lpPropSheet)
  1078.     {
  1079.         lpwd = (LPWIZDATA)lpPropSheet->lParam;
  1080.     }
  1081.     switch(message)
  1082.     {
  1083.         case WM_NOTIFY:
  1084.             lpnm = (NMHDR FAR *)lParam;
  1085.             switch(lpnm->code)
  1086.             {
  1087.                BOOL bForceWx86;
  1088.                case PSN_SETACTIVE:
  1089.                     lpwd->hwnd = hDlg;
  1090.                     if (lpwd->dwFlags & WDFLAG_NOBROWSEPAGE)
  1091.                     {
  1092.                         SetDlgMsgResult(hDlg, WM_NOTIFY, -1);
  1093.                     }
  1094.                     else
  1095.                     {
  1096.                         BrowseSetActive(lpwd);
  1097.                     }
  1098.                     break;
  1099.                case PSN_WIZNEXT:
  1100.                     // Remember the previous "InstallMode"
  1101.                     lpwd->bPrevMode = TermsrvAppInstallMode();
  1102.                     // Set the "InstallMode"
  1103.                     SetTermsrvAppInstallMode(TRUE);
  1104. #ifdef WX86
  1105.                     bForceWx86 = bWx86Enabled && bForceX86Env;
  1106. #else
  1107.                     bForceWx86 = FALSE;
  1108. #endif
  1109.                     if (!NextPushed(lpwd) || !SetupCleanupExePath(lpwd) ||
  1110.                           !ExecSetupProg(lpwd, bForceWx86, FALSE))
  1111.                     {
  1112.                         SetDlgMsgResult(hDlg, WM_NOTIFY, -1);
  1113.                     }
  1114.                     break;
  1115.                case PSN_WIZFINISH:
  1116.                   {
  1117. #ifdef WX86
  1118.                     bForceWx86 = bWx86Enabled && bForceX86Env;
  1119. #else
  1120.                     bForceWx86 = FALSE;
  1121. #endif
  1122.                     if (!SetupCleanupExePath(lpwd) ||
  1123.                         !ExecSetupProg(lpwd, bForceWx86, TRUE))
  1124.                     {
  1125.                         BrowseSetActive(lpwd);
  1126.                         SetDlgMsgResult(hDlg, WM_NOTIFY, -1);
  1127.                     }
  1128.                     break;
  1129.                  }
  1130.                case PSN_RESET:
  1131.                     CleanUpWizData(lpwd);
  1132.                     break;
  1133.                default:
  1134.                   return FALSE;
  1135.             }
  1136.             break;
  1137.         case WM_INITDIALOG:
  1138.             BrowseInitPropSheet(hDlg, lParam);
  1139.             break;
  1140.         case WMPRIV_POKEFOCUS:
  1141.             {
  1142.             HWND hCmd = GetDlgItem(hDlg, IDC_COMMAND);
  1143.             SetFocus(hCmd);
  1144.             Edit_SetSel(hCmd, 0, -1);
  1145.             break;
  1146.             }
  1147.         case WM_DESTROY:
  1148.         case WM_HELP:
  1149.         case WM_CONTEXTMENU:
  1150.             break;
  1151.         case WM_COMMAND:
  1152.             switch (GET_WM_COMMAND_ID(wParam, lParam))
  1153.             {
  1154.                 case IDHELP:
  1155.                         break;
  1156.                 case IDC_COMMAND:
  1157.                     switch (GET_WM_COMMAND_CMD(wParam, lParam))
  1158.                     {
  1159.                         case EN_CHANGE:
  1160.                             SetBrowseButtons(lpwd);
  1161.                             break;
  1162.                     }
  1163.                     break;
  1164.                 case IDC_BROWSE:
  1165.                     BrowsePushed(lpwd);
  1166.                     break;
  1167.             } // end of switch on WM_COMMAND
  1168.             break;
  1169.         default:
  1170.             return FALSE;
  1171.     } // end of switch on message
  1172.     return TRUE;
  1173. }  // SetupBrowseDlgProc