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

Windows Kernel

Development Platform:

Visual C++

  1. /*++
  2. Microsoft Confidential
  3. Copyright (c) 1992-1997  Microsoft Corporation
  4. All rights reserved
  5. Module Name:
  6.     strtlst.c
  7. Abstract:
  8.     Implements the controls in the "Startup" group on the
  9.     Startup/Recovery dialog of the System Control Panel Applet
  10. Revision History:
  11.     23-Jan-1996 JonPa
  12.         ported from NT3.51's system.cpl
  13. --*/
  14. #include "sysdm.h"
  15. ///////////////////////////////////////////////////////////////
  16. //          Persistant  vars
  17. ///////////////////////////////////////////////////////////////
  18. static TCHAR *pszBoot = NULL;
  19. static int nOriginalSelection;
  20. static int nOriginalTimeout;
  21. /*
  22.  * These functions in SETUPDLL.DLL are ANSI only!!!!
  23.  *
  24.  * Therefore any functions working with this DLL MUST remain ANSI only.
  25.  * The functions are GetRGSZEnvVar and UpdateNVRAM.
  26.  * The structure CPEnvBuf MUST also remain ANSI only.
  27.  */
  28. typedef int (WINAPI *GETNVRAMPROC)(CHAR **, USHORT, CHAR *, USHORT);
  29. typedef int (WINAPI *WRITENVRAMPROC)(DWORD, PSZ *, PSZ *);
  30. #ifdef _X86_
  31. char szBootIniA[]     = "c:\boot.ini";
  32. TCHAR szBootIni[]     = TEXT( "c:\boot.ini" );
  33. TCHAR szBootLdr[]     = TEXT( "boot loader" );
  34. TCHAR szFlexBoot[]    = TEXT( "flexboot" );
  35. TCHAR szMultiBoot[]   = TEXT( "multiboot" );
  36. TCHAR szTimeout[]     = TEXT( "timeout" );
  37. TCHAR szDefault[]     = TEXT( "default" );
  38. char szOSA[]          = "operating systems";
  39. #define BUFZ        4096
  40. //
  41. // For NEC PC98. Following definition comes from userinckbd.h.
  42. // The value must be the same as value in kbd.h.
  43. //
  44. #define NLSKBD_OEM_NEC   0x0D
  45. TCHAR x86DetermineSystemPartition( IN HWND hdlg );
  46. #endif
  47.      // v-pshuan: since the Silicon Graphics visual workstations boot
  48.      // ARC style, this code needs to be compiled for _X86_ as well.
  49. static HMODULE hmodSetupDll;   // hmod for setup - has api we need
  50. static GETNVRAMPROC fpGetNVRAMvar;  // address of function for getting nvram vars
  51. BOOL fCanUpdateNVRAM;
  52. #define MAX_BOOT_ENTRIES 10
  53. typedef struct tagEnvBuf
  54. {
  55.   int     cEntries;
  56.   CHAR *  pszVars[MAX_BOOT_ENTRIES];
  57.   // v-pshuan: this implies a maximum of 10 boot entries are supported
  58.   // although no error checking is performed in the existing parsing code
  59.   // to make sure there aren't more than 10 boot entries.
  60. } CPEnvBuf;
  61. //*************************************************************
  62. //
  63. //  StringToIntA
  64. //
  65. //  Purpose:    atoi
  66. //
  67. //  Parameters: LPSTR sz - pointer of string to convert
  68. //
  69. //  Return:     void
  70. //
  71. //  WARNING:  Unlike StringToInt, this one does not skip leading
  72. //  white space
  73. //
  74. //*************************************************************
  75. int StringToIntA( LPSTR sz ) {
  76.     int i = 0;
  77.     while( IsDigit( *sz ) ) {
  78.         i = i * 10 + (*sz - '0');
  79.         sz++;
  80.     }
  81.     return i;
  82. }
  83. //*************************************************************
  84. //
  85. //  IntToStringA
  86. //
  87. //  Purpose:    itoa
  88. //
  89. //  Parameters: INT    i    - integer to convert
  90. //              LPSTR sz   - pointer where to put the result
  91. //
  92. //  Return:     void
  93. //
  94. //*************************************************************
  95. #define CCH_MAX_DEC 12         // Number of chars needed to hold 2^32
  96. void IntToStringA( INT i, LPSTR sz) {
  97.     CHAR szTemp[CCH_MAX_DEC];
  98.     int iChr;
  99.     iChr = 0;
  100.     do {
  101.         szTemp[iChr++] = '0' + (i % 10);
  102.         i = i / 10;
  103.     } while (i != 0);
  104.     do {
  105.         iChr--;
  106.         *sz++ = szTemp[iChr];
  107.     } while (iChr != 0);
  108.     *sz++ = '';
  109. }
  110. ////////////////////////////////////////////////////////////////////////////
  111. //  CP_MAX_ENV assumes entire env. var. value < maxpath +
  112. //  add 20 for various quotes
  113. //  and 10 more for commas (see list description below)
  114. ////////////////////////////////////////////////////////////////////////////
  115. #define CP_MAX_ENV   (MAX_PATH + 30)
  116. CPEnvBuf CPEBOSLoadIdentifier;
  117. BOOL fAutoLoad;
  118. //////////////////////////////////////////////////////////////////////
  119. //
  120. // Identify whether we are running on an x86 system which nevertheless
  121. // boots using the ARC path (no c:boot.ini)
  122. //
  123. //////////////////////////////////////////////////////////////////////
  124. BOOL Is_ARCx86(void)
  125. {
  126.     TCHAR identifier[256];
  127.     ULONG identifierSize = sizeof(identifier);
  128.     HKEY hSystemKey = NULL;
  129.     BOOL rval = FALSE;
  130.     if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  131.                      TEXT("HARDWARE\DESCRIPTION\System"),
  132.                      0,
  133.                      KEY_QUERY_VALUE,
  134.                      &hSystemKey) == ERROR_SUCCESS) {
  135.         if ((RegQueryValueEx(hSystemKey,
  136.                              TEXT("Identifier"),
  137.                              NULL,
  138.                              NULL,
  139.                              (LPBYTE) identifier,
  140.                              &identifierSize) == ERROR_SUCCESS) &&
  141.             (wcsstr(identifier, TEXT("ARCx86")) != NULL)) {
  142.             rval = TRUE;
  143.         }
  144.         RegCloseKey(hSystemKey);
  145.     }
  146.     return rval;
  147. }
  148. ////////////////////////////////////////////////////////////////////////////
  149. //
  150. //  This routine will query the ARC NVRAM for an option passed
  151. //  in szName and fill in the argv style pointer passed in.
  152. //
  153. ////////////////////////////////////////////////////////////////////////////
  154. BOOL GetRGSZEnvVar(CPEnvBuf * pEnvBuf, PCHAR pszName)
  155. {
  156.     CHAR   *pszCur, *p;
  157.     int     cb, i;
  158.     CHAR   *rgtmp[1];
  159.     CHAR    rgchOut[CP_MAX_ENV*MAX_BOOT_ENTRIES];
  160.     // GetNVRAMVar takes an argv[] style paramater as input, so crock
  161.     // one up.
  162.     rgtmp[0] = pszName;
  163.     // GetNVRAMVar returns a 'list' of the form
  164.     //   open-curly"string1","string2","string3"close-curly
  165.     //
  166.     // an empty environment string will be 5 bytes:
  167.     // open-curly""close-curly[null-terminator]
  168.     cb = fpGetNVRAMvar (rgtmp, (USHORT)1,
  169.                 rgchOut, (USHORT) CP_MAX_ENV*MAX_BOOT_ENTRIES);
  170.     pEnvBuf->cEntries = 0;
  171.     // if cb was equal to 5, the string was empty (see above comment)
  172.     if (cb > 5)
  173.     {
  174.         // break the string up into array of separate strings that
  175.         // can be put into a listbox.
  176.         pszCur = rgchOut;
  177.         // skip first open-curly brace
  178.         pszCur++;
  179.         // counter for array of strings
  180.         i = 0;
  181.         while (*pszCur != '}')
  182.         {
  183.             p = pEnvBuf->pszVars[i] = MemAlloc (LPTR, MAX_PATH);
  184.             // skip first quote
  185.             pszCur++;
  186.             while (*pszCur != '"')
  187.                *p++ = *pszCur++;
  188.             // skip the close quote
  189.             pszCur++;
  190.             // null terminate destination
  191.             *p = '';
  192.             // skip the comma if not at end of string
  193.             if (*pszCur == ',')
  194.             {
  195.                pszCur++;
  196.                // and go to next string
  197.             }
  198.             i++;
  199.         }
  200.         pEnvBuf->cEntries = i;
  201.     }
  202.     return pEnvBuf->cEntries;
  203. }
  204. ////////////////////////////////////////////////////////////////////////////
  205. //
  206. //  This routine will free the memory allocated by GetRGSZEnvVar
  207. //
  208. //  History:
  209. //      22-Apr-1996 JonPa   Created it.
  210. //
  211. ////////////////////////////////////////////////////////////////////////////
  212. void FreeRGSZEnvVar(CPEnvBuf * pEnvBuf) {
  213.     int i;
  214.     for( i = 0; i < pEnvBuf->cEntries; i++ ) {
  215.         MemFree( pEnvBuf->pszVars[i] );
  216.     }
  217. }
  218. ////////////////////////////////////////////////////////////////////////////
  219. // The user has made a choice among the entries.
  220. // Now we have to arrange all the strings stored in NVRAM so
  221. // that they  have the same ordering.  The selection is passed in,
  222. // so what this  function does is if selection is M, it makes the Mth item
  223. // appear first in each of the 5 environment strings and the other items
  224. // follow it in the list.
  225. //
  226. // Then if the timeout button is checked, it updates the AUTOLOAD variable
  227. // to "yes" and set the COUNTDOWN variable to the number of seconds in the
  228. // edit control.
  229. //
  230. // BUGBUG!!! - We need to add a bool parameter that indicates whether or
  231. // not the strings should be freed. 11-Mar-1996 JonPa
  232. //
  233. ////////////////////////////////////////////////////////////////////////////
  234. BOOL UpdateNVRAM(HWND hdlg, int selection, int timeout)
  235. {
  236.     CHAR *rgszVRAM[5] = { "SYSTEMPARTITION",
  237.                           "OSLOADER",
  238.                           "OSLOADPARTITION",
  239.                           "OSLOADFILENAME",
  240.                           "OSLOADOPTIONS"
  241.                         };
  242.     CPEnvBuf rgcpeb[5];
  243.     WRITENVRAMPROC fpWriteNVRAMVar;
  244.     int iTemp, jTemp;
  245.     CHAR *pszSwap;
  246.     CHAR szTemp[10];
  247.     HMODULE hmodSetupDLL;
  248.     BOOL bChecked;
  249.     // args and charray are needed for call to SetNVRamVar() in SETUP
  250.     PSZ args[2];
  251.     CHAR chArray[CP_MAX_ENV*MAX_BOOT_ENTRIES];
  252.     PSZ pszReturn;
  253.     if ((hmodSetupDll = LoadLibrary (TEXT("setupdll"))) == NULL)
  254.         return(FALSE);
  255.     fpWriteNVRAMVar = (WRITENVRAMPROC) GetProcAddress(hmodSetupDll, "SetNVRAMVar");
  256.     if (fpWriteNVRAMVar == NULL)
  257.         return(FALSE);
  258.     // 0 is always the selection when the dialog is brought up,
  259.     // so as an optimization don't update the nvram if it's
  260.     // not necessary.
  261.     if (selection != 0)
  262.     {
  263.        // read in the strings from NVRAM.  the number of strings (other than
  264.        // LOADIDENTIFIER is 5)
  265.        for (iTemp = 0; iTemp < 5; iTemp++)
  266.        {
  267.            GetRGSZEnvVar (&rgcpeb[iTemp], rgszVRAM[iTemp]);
  268.            // now re-order the strings to swap the 'selection-th' item
  269.            // string with the first string.
  270.            pszSwap = rgcpeb[iTemp].pszVars[0];
  271.            rgcpeb[iTemp].pszVars[0] = rgcpeb[iTemp].pszVars[selection];
  272.            rgcpeb[iTemp].pszVars[selection] = pszSwap;
  273.        }
  274.        // now do the same for the LOADIDENTIFIER, (this was set up earlier
  275.        // in the processing the INITDIALOG message).
  276.        pszSwap = CPEBOSLoadIdentifier.pszVars[0];
  277.        CPEBOSLoadIdentifier.pszVars[0] = CPEBOSLoadIdentifier.pszVars[selection];
  278.        CPEBOSLoadIdentifier.pszVars[selection] = pszSwap;
  279.        // now write to NVRAM:  first write LOADIDENTIFIER, then the other 5
  280.        // variables.
  281.        args[0] = (PSZ)"LOADIDENTIFIER";
  282.        args[1] = chArray;
  283.        chArray[0] = '';
  284.        for (iTemp = 0; iTemp < CPEBOSLoadIdentifier.cEntries; iTemp++)
  285.        {
  286.            lstrcatA (chArray, CPEBOSLoadIdentifier.pszVars[iTemp]);
  287.            lstrcatA (chArray, ";");
  288.        }
  289.        // remove the last semi-colon:
  290.        chArray[lstrlenA(chArray)-1] = '';
  291.        fpWriteNVRAMVar ((DWORD)2, args, &pszReturn);
  292.        for (iTemp = 0; iTemp < 5; iTemp++)
  293.        {
  294.            args[0] = rgszVRAM[iTemp];
  295.            args[1] = chArray;
  296.            chArray[0] = '';
  297.            for (jTemp = 0; jTemp < rgcpeb[iTemp].cEntries; jTemp++)
  298.            {
  299.                lstrcatA (chArray, rgcpeb[iTemp].pszVars[jTemp]);
  300.                lstrcatA (chArray, ";");
  301.            }
  302.            chArray[lstrlenA(chArray)-1] = '';
  303.            fpWriteNVRAMVar ((DWORD)2, args, &pszReturn);
  304.            // We are done with this variable... Free the resources it consumes
  305.            FreeRGSZEnvVar( &rgcpeb[iTemp] );
  306.        }
  307.     }
  308.     args[0] = "AUTOLOAD";
  309.     if (bChecked = IsDlgButtonChecked (hdlg, IDC_STARTUP_SYS_ENABLECOUNTDOWN))
  310.        args[1] = "YES";
  311.     else
  312.        args[1] = "";
  313.     fpWriteNVRAMVar ((DWORD)2, args, &pszReturn);
  314.     // This is a temporary hack workaround for the fact that the
  315.     // AUTOLOAD variable seems to be broken on Alpha
  316. //    if (bChecked)
  317. //    {
  318.        args[0] = "COUNTDOWN";
  319.        IntToStringA(timeout, szTemp);
  320.        args[1] = szTemp;
  321.        fpWriteNVRAMVar ((DWORD)2, args, &pszReturn);
  322. //    }
  323.     FreeLibrary (hmodSetupDll);
  324.     return TRUE;
  325. }
  326. #ifdef _X86_
  327. BOOL WriteableBootIni( LPTSTR szBootIni, HWND hDlg ) {
  328.     BOOL bOK;
  329.     DWORD dwFileAttr;
  330.     HANDLE hFile;
  331.     bOK = TRUE;
  332.     //  Change Read-only file attrs on Boot.ini file if necessary
  333.     if ((dwFileAttr = GetFileAttributes (szBootIni)) != 0xFFFFFFFF) {
  334.         if (dwFileAttr & FILE_ATTRIBUTE_READONLY) {
  335.             if (!SetFileAttributes (szBootIni, dwFileAttr & ~FILE_ATTRIBUTE_READONLY))
  336.             {
  337.                 bOK = FALSE;
  338.             }
  339.         }
  340.     }
  341.     if (bOK)
  342.     {
  343.         hFile = CreateFile( szBootIni, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ, NULL,
  344.                 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
  345.         if (hFile != INVALID_HANDLE_VALUE) {
  346.             CloseHandle(hFile);
  347.         } else {
  348.             if (GetLastError() == ERROR_FILE_NOT_FOUND || GetLastError() == ERROR_PATH_NOT_FOUND) {
  349.                 MsgBoxParam (hDlg, SYSTEM+39, INITS+1, MB_OK | MB_ICONEXCLAMATION, szBootIni);
  350.             }
  351.             bOK = FALSE;
  352.         }
  353.         //  Restore read-only attr, if necessary, after writes
  354.         if (dwFileAttr != 0xFFFFFFFF && (dwFileAttr & FILE_ATTRIBUTE_READONLY)) {
  355.             SetFileAttributes (szBootIni, dwFileAttr);
  356.         }
  357.     }
  358.     return bOK;
  359. }
  360. #endif
  361. void StartListInit( HWND hDlg, WPARAM wParam, LPARAM lParam ) {
  362.     HWND    hwndTemp;
  363.     HMODULE hmodSetupDll;
  364.     int     iTemp;
  365.     int     n;
  366. #ifdef _X86_
  367.     int     i, timeout;
  368.     TCHAR   szTemp2[MAX_PATH];
  369.     int     selection;
  370.     TCHAR  *pszKeyName;
  371.     LPTSTR  pszLine;
  372.     TCHAR  *pszValue;
  373.     TCHAR  *pszTemp;
  374.     LPTSTR  lpKey = NULL;
  375.     //  ANSI string pointers
  376.     LPSTR   pszSectionA;
  377. #endif
  378. #ifdef _X86_
  379.         if (Is_ARCx86())
  380. #endif
  381.         {
  382.         ////////////////////////////////////////////////////////////////////
  383.         //  Read info from NVRAM environment variables
  384.         ////////////////////////////////////////////////////////////////////
  385.         // Init to 0 so we won't try to free garbage if we cant load setup.dll
  386.         CPEBOSLoadIdentifier.cEntries = 0;
  387.         fCanUpdateNVRAM = FALSE;
  388.         fAutoLoad = FALSE;
  389.         hwndTemp = GetDlgItem (hDlg, IDC_STARTUP_SYS_OS);
  390.         if (hmodSetupDll = LoadLibrary(TEXT("setupdll")))
  391.         {
  392.             if (fpGetNVRAMvar = (GETNVRAMPROC)GetProcAddress(hmodSetupDll, "GetNVRAMVar"))
  393.             {
  394.                 if (fCanUpdateNVRAM = GetRGSZEnvVar (&CPEBOSLoadIdentifier, "LOADIDENTIFIER"))
  395.                 {
  396.                     for (iTemp = 0; iTemp < CPEBOSLoadIdentifier.cEntries; iTemp++)
  397.                         n = (int)SendMessageA (hwndTemp, CB_ADDSTRING, 0,
  398.                                           (LPARAM)CPEBOSLoadIdentifier.pszVars[iTemp]);
  399.                     // the first one is the selection we want (offset 0)
  400.                     SendMessage (hwndTemp, CB_SETCURSEL, 0, 0L);
  401.                     SendDlgItemMessage (hDlg, IDC_STARTUP_SYS_SECONDS,
  402.                               EM_LIMITTEXT, 3, 0L);
  403.                     SendDlgItemMessage (hDlg, IDC_STARTUP_SYS_SECSCROLL,
  404.                               UDM_SETRANGE, 0, (LPARAM)MAKELONG(999,0));
  405.                 }
  406.                 // fCanUpdateNVRAM is a global that gets set up above
  407.                 if (fCanUpdateNVRAM)
  408.                 {
  409.                    // This is a temporary hack workaround for the
  410.                    // fact that the AUTOLOAD variable seems to
  411.                    // be broken on Alpha
  412.                    CPEnvBuf cpebTimeout;
  413.                    int timeout;
  414.                    
  415.                    if (GetRGSZEnvVar(&cpebTimeout, "COUNTDOWN")) {
  416.                       timeout = StringToIntA(cpebTimeout.pszVars[0]);
  417.                       fAutoLoad = (BOOL) timeout;
  418.                       SetDlgItemInt(
  419.                          hDlg,
  420.                          IDC_STARTUP_SYS_SECONDS,
  421.                          timeout,
  422.                          FALSE
  423.                       );
  424.                       FreeRGSZEnvVar(&cpebTimeout);
  425.                    } // if
  426. #if 0
  427.                    CPEnvBuf cpebAutoLoad, cpebTimeout;
  428.                    // is Autoload == YES?  if so, check the checkbox
  429.                    //    and read setting for timeouts
  430.                    // autoload == NO? disable edit control.
  431.                    if (GetRGSZEnvVar (&cpebAutoLoad, "AUTOLOAD"))
  432.                    {
  433.                       if (!lstrcmpiA (cpebAutoLoad.pszVars[0], "yes"))
  434.                       {
  435.                          fAutoLoad = TRUE;
  436.                          if (GetRGSZEnvVar (&cpebTimeout, "COUNTDOWN")) {
  437.                             SetDlgItemInt (hDlg, IDC_STARTUP_SYS_SECONDS,
  438.                                            StringToIntA (cpebTimeout.pszVars[0]), FALSE);
  439.                             // We are done with cpebTimeout... Free the resources it consumes
  440.                             FreeRGSZEnvVar(&cpebTimeout);
  441.                          }
  442.                       }
  443.                       // We are done with cpebTimeout... Free the resources it consumes
  444.                       FreeRGSZEnvVar(&cpebAutoLoad);
  445.                    }
  446. #endif //0
  447.                    CheckDlgButton (hDlg, IDC_STARTUP_SYS_ENABLECOUNTDOWN, fAutoLoad);
  448.                    if (!fAutoLoad)
  449.                    {
  450.                        EnableWindow (GetDlgItem (hDlg, IDC_STARTUP_SYS_SECONDS), FALSE);
  451.                        EnableWindow (GetDlgItem (hDlg, IDC_STARTUP_SYS_SECSCROLL), FALSE);
  452.                    }
  453.                 }
  454.                 else
  455.                 {
  456.                    // if can't set variables (no privilege), disable controls
  457.                    EnableWindow (GetDlgItem(hDlg, IDC_STARTUP_SYS_SECONDS), FALSE);
  458.                    EnableWindow (GetDlgItem(hDlg, IDC_STARTUP_SYS_SECONDS_LABEL), FALSE);
  459.                    EnableWindow (GetDlgItem(hDlg, IDC_STARTUP_SYS_ENABLECOUNTDOWN), FALSE);
  460.                    EnableWindow (GetDlgItem(hDlg, IDC_STARTUP_SYS_SECSCROLL), FALSE);
  461.                    EnableWindow (GetDlgItem(hDlg, IDC_STARTUP_SYS_OS), FALSE);
  462.                 }
  463.             }
  464.             FreeLibrary (hmodSetupDll);
  465.         }
  466.         // default to 5 seconds for now.
  467.         }
  468. #ifdef _X86_
  469.         else
  470.         {
  471.         ////////////////////////////////////////////////////////////////////
  472.         //  Read info from boot.ini file and initialize OS Group box items
  473.         ////////////////////////////////////////////////////////////////////
  474.         InitializeArcStuff();
  475.         //
  476.         //  Get correct Boot Drive - this was added because after someone
  477.         //  boots the system, they can ghost or change the drive letter
  478.         //  of their boot drive from "c:" to something else.
  479.         //
  480.         if (IsNEC_98)
  481.         {
  482.             //
  483.             // For NEC PC98.
  484.             // For Install NT to non C: drive.
  485.             // Get drive letter of system directory.
  486.             //
  487.             if ((HIBYTE(LOWORD(GetKeyboardType(1))) & 0xff) == NLSKBD_OEM_NEC) {
  488.                 TCHAR   szSystemDirectory[MAX_PATH];
  489.                 GetSystemDirectory (szSystemDirectory, ARRAYSIZE(szSystemDirectory));
  490.                 szBootIni[0] = szSystemDirectory[0];
  491.             } else {
  492.                 //
  493.                 // PC/AT
  494.                 //
  495. //                szBootIni[0] = GetBootDrive();
  496.                   szBootIni[0] = x86DetermineSystemPartition (hDlg);
  497.             }
  498.         }
  499.         else
  500.         {
  501. //            szBootIni[0] = GetBootDrive();
  502.             szBootIni[0] = x86DetermineSystemPartition (hDlg);
  503.         }
  504.         szBootIniA[0] = (char) szBootIni[0];
  505.         //
  506.         //  Make sure we have access to BOOT.INI
  507.         //
  508.         if (!WriteableBootIni(szBootIni, hDlg)) {
  509.             // if can't set variables (no privilege), disable controls
  510.             EnableWindow (GetDlgItem(hDlg, IDC_STARTUP_SYS_SECONDS), FALSE);
  511.             EnableWindow (GetDlgItem(hDlg, IDC_STARTUP_SYS_SECONDS_LABEL), FALSE);
  512.             EnableWindow (GetDlgItem(hDlg, IDC_STARTUP_SYS_ENABLECOUNTDOWN), FALSE);
  513.             EnableWindow (GetDlgItem(hDlg, IDC_STARTUP_SYS_SECSCROLL), FALSE);
  514.             EnableWindow (GetDlgItem(hDlg, IDC_STARTUP_SYS_OS), FALSE);
  515.         }
  516.         //
  517.         //  Determine which section [boot loader]
  518.         //                          [flexboot]
  519.         //                       or [multiboot] is in file
  520.         //
  521.         n = GetPrivateProfileString (szBootLdr, NULL, NULL, szTemp2,
  522.                                      ARRAYSIZE(szTemp2), szBootIni);
  523.         if (n != 0)
  524.             pszBoot = szBootLdr;
  525.         else
  526.         {
  527.             n = GetPrivateProfileString (szFlexBoot, NULL, NULL, szTemp2,
  528.                                          ARRAYSIZE(szTemp2), szBootIni);
  529.             if (n != 0)
  530.                 pszBoot = szFlexBoot;
  531.             else
  532.             {
  533.                 n = GetPrivateProfileString (szMultiBoot, NULL, NULL, szTemp2,
  534.                                              ARRAYSIZE(szTemp2), szBootIni);
  535.                 if (n != 0)
  536.                 {
  537.                     pszBoot = szMultiBoot;
  538.                 }
  539.                 else
  540.                 {
  541.                     //
  542.                     //  This final case is here because I want to DEFAULT
  543.                     //  to "[boot loader]" as the section name to use in
  544.                     //  the event that we do not find any section in the
  545.                     //  boot.ini file.
  546.                     //
  547.                     pszBoot = szBootLdr;
  548.                 }
  549.             }
  550.         }
  551.         //  Get info under [*pszBoot] section - timeout & default OS path
  552.         timeout = GetPrivateProfileInt (pszBoot, szTimeout, 0, szBootIni);
  553.         SetDlgItemInt (hDlg, IDC_STARTUP_SYS_SECONDS, timeout, FALSE);
  554.         nOriginalTimeout = timeout;
  555.         //
  556.         //  Get the "Default" os selection
  557.         //
  558.         szTemp2[0] = TEXT('');
  559.         GetPrivateProfileString (pszBoot, szDefault, NULL, szTemp2,
  560.                                  ARRAYSIZE(szTemp2), szBootIni);
  561.         //
  562.         //  Display all choices under [operating system] in boot.ini file
  563.         //  in combobox for selection
  564.         //
  565.         hwndTemp = GetDlgItem (hDlg, IDC_STARTUP_SYS_OS);
  566.         selection = -1;
  567.         //
  568.         //  ANSI Buffer!
  569.         //
  570.         pszSectionA = (LPSTR) MemAlloc (LPTR, BUFZ);
  571.         //
  572.         //  Get entire section under OS to properly show user choices
  573.         //
  574.         n = GetPrivateProfileSectionA (szOSA, pszSectionA, BUFZ, szBootIniA);
  575.         if ((n >= BUFZ-2) || (n == 0))
  576.         {
  577. ErrorReadingSection:
  578.             //  Error reading data
  579.             MemFree ((LPVOID)pszSectionA);
  580.             goto ContinueSystemInit;
  581.         }
  582.         //
  583.         //  Check for api errors and NoOptions
  584.         //
  585.         if ((pszSectionA == NULL) || ((*pszSectionA == '') && (*(pszSectionA+1) == '')))
  586.             goto ErrorReadingSection;
  587.         lpKey = MemAlloc (LPTR, BUFZ*sizeof(TCHAR));
  588.         pszKeyName = lpKey;
  589.         //
  590.         //  Convert entire buffer from OEM to UNICODE
  591.         //
  592.         MultiByteToWideChar (CP_OEMCP, MB_PRECOMPOSED, pszSectionA, n+2, pszKeyName, BUFZ);
  593.         MemFree ((LPVOID)pszSectionA);
  594.         //
  595.         //  Continue until we reach end of buffer, marked by Double ''
  596.         //
  597.         while (*(pszKeyName+1) != TEXT(''))
  598.         {
  599.             pszLine = pszKeyName;
  600.             //
  601.             //  Get pointer to next line in buffer.
  602.             //
  603.             pszKeyName += lstrlen (pszKeyName) + 1;
  604.             //
  605.             //  Find LHS/RHS delimiter to separate strings
  606.             //
  607.             pszValue = StrStr(pszLine, TEXT("="));
  608.             if (pszValue && (pszValue != pszLine))
  609.             {
  610.                 *pszValue = '';
  611.                 pszValue++;
  612.             }
  613.             else
  614.             {
  615.                 pszValue = pszLine;
  616.             }
  617.             //
  618.             //  Put it into combobox (if no descriptive name, use path)
  619.             //
  620.             n = (int)SendMessage (hwndTemp, CB_ADDSTRING, 0, (LPARAM) (LPTSTR) pszValue);
  621.             //
  622.             //  Find the first selection that matches the "default" selection
  623.             //
  624.             if ((selection == -1)  && !lstrcmp (pszLine, szTemp2))
  625.                 selection = n;
  626.             //
  627.             //  Also attach pointer to KeyName (i.e. boot path) to each item
  628.             //
  629.             pszTemp = CloneString (pszLine);
  630.             SendMessage (hwndTemp, CB_SETITEMDATA, n, (LPARAM)pszTemp);
  631.         }
  632.         // If no selection was found up to this point, choose 0, because
  633.         // that is the default value that loader would choose.
  634.         if (selection == -1)
  635.             selection = 0;
  636.         SendDlgItemMessage (hDlg, IDC_STARTUP_SYS_SECONDS, EM_LIMITTEXT, 3, 0L);
  637.         SendDlgItemMessage (hDlg, IDC_STARTUP_SYS_SECSCROLL,
  638.                               UDM_SETRANGE, 0, (LPARAM)MAKELONG(999,0));
  639.         //  Check or uncheck the checkbox based on the timeout value
  640.         SendDlgItemMessage(
  641.             hDlg,
  642.             IDC_STARTUP_SYS_ENABLECOUNTDOWN,
  643.             BM_SETCHECK,
  644.             (WPARAM) (BOOL) timeout,
  645.             (LPARAM) 0L
  646.         );
  647.         EnableWindow(
  648.             GetDlgItem(hDlg, IDC_STARTUP_SYS_SECONDS), 
  649.             (BOOL) timeout
  650.         );
  651.         EnableWindow(
  652.             GetDlgItem(hDlg, IDC_STARTUP_SYS_SECSCROLL), 
  653.             (BOOL) timeout
  654.         );
  655.         //  This call should force correct settings for the checkbox
  656.         //  and "Showlist for xx seconds" controls
  657.         nOriginalSelection = selection;
  658.         SendMessage (hwndTemp, CB_SETCURSEL, selection, 0L);
  659. ContinueSystemInit:
  660.         if (lpKey) {
  661.             MemFree (lpKey);
  662.         }
  663.         }
  664. #endif  // _X86_
  665. }
  666. //
  667. // BUGBUG!!! - We need an and extra parameter that indicates
  668. //  whether we should save the variables out or not.
  669. //
  670. //  IE. We need to handle CANCEL case.
  671. //
  672. int StartListExit(HWND hDlg, WPARAM wParam, LPARAM lParam ) {
  673.     HWND hwndTemp;
  674.     int  selection, timeout;
  675. #ifdef _X86_
  676.     DWORD dwFileAttr;
  677.     BOOL bOK;
  678.     HANDLE  hKey;
  679.     TCHAR  *pszKeyName;
  680.     int     i, n;
  681.     DWORD   dwBufz;
  682.     LPSTR   pszSectionA;
  683.     TCHAR  *pszTemp;
  684.     TCHAR   szTemp[MAX_PATH];
  685.     TCHAR   szTemp2[MAX_PATH];
  686.     int     iTemp;
  687. #endif
  688.     /////////////////////////////////////////////////////////////////
  689.     //  Write new info to boot.ini file
  690.     /////////////////////////////////////////////////////////////////
  691.     hwndTemp = GetDlgItem (hDlg, IDC_STARTUP_SYS_OS);
  692.     selection = (int)SendMessage (hwndTemp, CB_GETCURSEL, 0, 0L);
  693.     if ((selection == CB_ERR) || (selection == CB_ERRSPACE))
  694.         selection = nOriginalSelection;
  695.     timeout   = GetDlgItemInt (hDlg, IDC_STARTUP_SYS_SECONDS, NULL, FALSE);
  696. #ifdef _X86_
  697.     if (Is_ARCx86())
  698. #endif
  699.     {
  700.     if (fCanUpdateNVRAM) {
  701.         TCHAR szTextNew[MAX_PATH];
  702.         TCHAR szTextTop[MAX_PATH];
  703.         UpdateNVRAM (hDlg, selection, timeout);
  704.         /*
  705.          * Now reorder list to match NVRAM
  706.          */
  707.         // Get the current text
  708.         SendMessage( hwndTemp, CB_GETLBTEXT, selection, (LPARAM)szTextNew );
  709.         SendMessage( hwndTemp, CB_GETLBTEXT,         0, (LPARAM)szTextTop );
  710.         // Set the new text to the 0th entry in the list
  711.         SendMessage( hwndTemp, CB_DELETESTRING, 0, 0 );
  712.         SendMessage( hwndTemp, CB_INSERTSTRING, 0, (LPARAM)szTextNew);
  713.         // Set old top text selected item
  714.         SendMessage( hwndTemp, CB_DELETESTRING, selection, 0 );
  715.         SendMessage( hwndTemp, CB_INSERTSTRING, selection, (LPARAM)szTextTop);
  716.         // Now point the current selection back to the top of the list, so it matches
  717.         // what the user just chose
  718.         SendMessage( hwndTemp, CB_SETCURSEL, 0, 0);
  719.     }
  720.     }
  721. #ifdef _X86_
  722.     else
  723.     {
  724.     if ((selection != nOriginalSelection) || (timeout != nOriginalTimeout))
  725.     {
  726.         bOK = TRUE;
  727.         //  Change Read-only file attrs on Boot.ini file if necessary
  728.         if ((dwFileAttr = GetFileAttributes (szBootIni)) != 0xFFFFFFFF)
  729.             if (dwFileAttr & FILE_ATTRIBUTE_READONLY)
  730.                 if (!SetFileAttributes (szBootIni,
  731.                            dwFileAttr & ~FILE_ATTRIBUTE_READONLY))
  732.                 {
  733. BootIniWriteError:
  734.                     bOK = FALSE;
  735.                     MsgBoxParam (hDlg, SYSTEM+19, INITS+1, MB_OK | MB_ICONINFORMATION);
  736.                 }
  737.         if (bOK)
  738.         {
  739.             //
  740.             //  Write new [operating systems] section and
  741.             //  set "default" selection in boot.ini file.
  742.             //
  743.             if (selection != nOriginalSelection)
  744.             {
  745.                 //
  746.                 //  Allocate buffers for new section
  747.                 //
  748.                 hKey = MemAlloc (LPTR, BUFZ*sizeof(TCHAR));
  749.                 pszKeyName = (TCHAR *) hKey;
  750.                 //
  751.                 //  Total profile section buffer size
  752.                 //
  753.                 i = dwBufz = 0;
  754.                 pszSectionA = (LPSTR) MemAlloc (LPTR, BUFZ);
  755.                 //
  756.                 //  Get the User's selection and write it in the
  757.                 //  section buffer first.  Then get all other items.
  758.                 //
  759.                 pszTemp = (LPTSTR) SendMessage (hwndTemp,
  760.                                                 CB_GETITEMDATA,
  761.                                                 selection, 0L);
  762.                 SendMessage (hwndTemp, CB_GETLBTEXT, selection,
  763.                               (LPARAM) (LPTSTR) szTemp);
  764.                 if (pszTemp != (LPTSTR) CB_ERR)
  765.                 {
  766.                     lstrcpy (pszKeyName, pszTemp);
  767.                     lstrcat (pszKeyName, TEXT("="));
  768.                     lstrcat (pszKeyName, szTemp);
  769.                     i = lstrlen (pszKeyName) + 1;
  770.                     pszKeyName += i;
  771.                     //
  772.                     //  Set "default" selection in boot.ini file
  773.                     //
  774.                     if (!WritePrivateProfileString (pszBoot,
  775.                                                     szDefault,
  776.                                                     pszTemp,
  777.                                                     szBootIni))
  778.                     {
  779.                        goto BootIniWriteError;
  780.                     }
  781.                 }
  782.                 dwBufz = (DWORD) i;
  783.                 //
  784.                 //  Get the rest of the selections
  785.                 //
  786.                 n = (int)SendMessage (hwndTemp, CB_GETCOUNT, 0, 0L);
  787.                 if (n != LB_ERR)
  788.                 {
  789.                     for (iTemp = 0; iTemp < n; iTemp++)
  790.                     {
  791.                         //
  792.                         //  Skip the User's selection since we got it
  793.                         //  above.
  794.                         //
  795.                         if (iTemp == selection)
  796.                             continue;
  797.                         pszTemp = (LPTSTR) SendMessage (hwndTemp,
  798.                                                         CB_GETITEMDATA,
  799.                                                         iTemp, 0L);
  800.                         SendMessage (hwndTemp, CB_GETLBTEXT, iTemp,
  801.                                      (LPARAM) (LPTSTR) szTemp);
  802.                         if (pszTemp != (LPTSTR) CB_ERR)
  803.                         {
  804.                             lstrcpy (pszKeyName, pszTemp);
  805.                             lstrcat (pszKeyName, TEXT("="));
  806.                             lstrcat (pszKeyName, szTemp);
  807.                             i = lstrlen (pszKeyName) + 1;
  808.                             pszKeyName += i;
  809.                             dwBufz += (DWORD) i;
  810.                         }
  811.                     }
  812.                 }
  813.                 //
  814.                 //  Double-Null terminate the buffer
  815.                 //
  816.                 *pszKeyName = TEXT('');
  817.                 dwBufz++;
  818.                 pszKeyName = (TCHAR *) hKey;
  819.                 //
  820.                 //  Convert entire buffer from UNICODE to OEM
  821.                 //
  822.                 WideCharToMultiByte (CP_OEMCP, WC_COMPOSITECHECK,
  823.                                      pszKeyName, dwBufz,
  824.                                      pszSectionA, BUFZ,
  825.                                      NULL, NULL);
  826.                 //
  827.                 //  Write new section under OS
  828.                 //
  829.                 if (!WritePrivateProfileSectionA (szOSA,
  830.                                                   pszSectionA,
  831.                                                   szBootIniA))
  832.                 {
  833.                     MemFree ((LPVOID)pszSectionA);
  834.                     MemFree ((LPVOID)hKey);
  835.                     goto BootIniWriteError;
  836.                 }
  837.                 MemFree ((LPVOID)pszSectionA);
  838.                 MemFree ((LPVOID)hKey);
  839.             }
  840.             if (timeout != nOriginalTimeout)
  841.             {
  842.                 GetDlgItemText (hDlg, IDC_STARTUP_SYS_SECONDS, szTemp2, sizeof(szTemp2));
  843.                 if (!CheckVal (hDlg, IDC_STARTUP_SYS_SECONDS, FORMIN, FORMAX, SYSTEM+4))
  844.                     return RET_BREAK;
  845.                 //  Write timeout value to file
  846.                 if (!WritePrivateProfileString (pszBoot, szTimeout,
  847.                                                szTemp2, szBootIni))
  848.                     goto BootIniWriteError;
  849.             }
  850.             //  Restore read-only attr, if necessary, after writes
  851.             if (dwFileAttr != 0xFFFFFFFF && (dwFileAttr & FILE_ATTRIBUTE_READONLY)) {
  852.                     SetFileAttributes (szBootIni, dwFileAttr);
  853.             }
  854.         }
  855.     }
  856.     }
  857. #endif // _X86_
  858.     return RET_CONTINUE;
  859. }
  860. BOOL CheckVal( HWND hDlg, WORD wID, WORD wMin, WORD wMax, WORD wMsgID )
  861. {
  862.     WORD nVal;
  863.     BOOL bOK;
  864.     HWND hVal;
  865.     WCHAR szTemp[FOR_MAX_LENGTH];
  866.     if( wMin > wMax )
  867.     {
  868.         nVal = wMin;
  869.         wMin = wMax;
  870.         wMax = nVal;
  871.     }
  872.     nVal = (WORD) GetDlgItemInt( hDlg, wID, &bOK, FALSE );
  873.     //
  874.     // This is a hack to make the null string act equivalent to zero
  875.     //
  876.     if (!bOK) {
  877.        bOK = !GetDlgItemTextW( hDlg, wID, szTemp, FOR_MAX_LENGTH );
  878.     }
  879.     if( !bOK || ( nVal < wMin ) || ( nVal > wMax ) )
  880.     {
  881.         MsgBoxParam( hDlg, wMsgID, INITS + 1,
  882.                       MB_OK | MB_ICONERROR, wMin, wMax );
  883.         SendMessage( hDlg, WM_NEXTDLGCTL,
  884.                      (WPARAM) ( hVal = GetDlgItem( hDlg, wID ) ), 1L );
  885. //        SendMessage(hVal, EM_SETSEL, NULL, MAKELONG(0, 32767));
  886.         SendMessage( hVal, EM_SETSEL, 0, 32767 );
  887.         return( FALSE );
  888.     }
  889.     return( TRUE );
  890. }
  891. //////////////////////////////////////////////////////
  892. //
  893. // Frees the data (if any) associated with the strings in the combo box
  894. //
  895. //////////////////////////////////////////////////////
  896. void StartListDestroy(HWND hDlg, WPARAM wParam, LPARAM lParam) {
  897. #ifdef _X86_
  898.     if (Is_ARCx86())
  899. #endif
  900.     {
  901.     // Reference vars to make compiler happy
  902.     FreeRGSZEnvVar(&CPEBOSLoadIdentifier);
  903.     return;
  904.     (void)hDlg;
  905.     (void)wParam;
  906.     (void)lParam;
  907.     }
  908. #ifdef _X86_
  909.     else
  910.     {
  911.     // Only X86 has data in the combo
  912.     int     n;
  913.     HWND    hwndTemp;
  914.     int     iTemp;
  915.     TCHAR   *pszTemp;
  916.     //
  917.     //  Free strings stored in the listbox
  918.     //
  919.     hwndTemp = GetDlgItem (hDlg, IDC_STARTUP_SYS_OS);
  920.     n = (int)SendMessage (hwndTemp, CB_GETCOUNT, 0, 0L);
  921.     if (n != LB_ERR)
  922.     {
  923.         for (iTemp = 0; iTemp < n; iTemp++)
  924.         {
  925.             pszTemp = (LPTSTR) SendMessage (hwndTemp,
  926.                                             CB_GETITEMDATA,
  927.                                             iTemp, 0L);
  928.             if (pszTemp != (LPTSTR) CB_ERR)
  929.             {
  930.                 MemFree (pszTemp);
  931.             }
  932.         }
  933.     }
  934.     }
  935. #endif // _X86_
  936. }