|
|
// Created 07-Jan-1993 11:20am by Jeff Parsons
#include "shellprv.h"
#pragma hdrstop
#include <setupapi.h>
#ifdef _X86_
const TCHAR szRegKeyMSDOSApps[] = REGSTR_PATH_NEWDOSBOX;
const TCHAR szParams[] = KEY_PARAMS; const TCHAR szBatchFile[] = KEY_BATCHFILE; const TCHAR szLowMem[] = KEY_LOWMEM; const TCHAR szEmsMem[] = KEY_EMSMEM; const TCHAR szXmsMem[] = KEY_XMSMEM; const TCHAR szDpmiMem[] = KEY_DPMIMEM; const TCHAR szEnable[] = KEY_ENABLE; const TCHAR szDisable[] = KEY_DISABLE;
const TCHAR szWindowed[] = KEYVAL_WINDOWED; const TCHAR szBackground[] = KEYVAL_BACKGROUND; const TCHAR szExclusive[] = KEYVAL_EXCLUSIVE; const TCHAR szDetectIdle[] = KEYVAL_DETECTIDLE; const TCHAR szLowLocked[] = KEYVAL_LOWLOCKED; const TCHAR szEMSLocked[] = KEYVAL_EMSLOCKED; const TCHAR szXMSLocked[] = KEYVAL_XMSLOCKED; const TCHAR szUseHMA[] = KEYVAL_USEHMA; const TCHAR szEmulateROM[] = KEYVAL_EMULATEROM; const TCHAR szRetainVRAM[] = KEYVAL_RETAINVRAM; const TCHAR szFastPaste[] = KEYVAL_FASTPASTE; const TCHAR szALTTAB[] = KEYVAL_ALTTAB; const TCHAR szALTESC[] = KEYVAL_ALTESC; const TCHAR szCTRLESC[] = KEYVAL_CTRLESC; const TCHAR szPRTSCRN[] = KEYVAL_PRTSCRN; const TCHAR szALTPRTSCRN[] = KEYVAL_ALTPRTSCRN; const TCHAR szALTSPACE[] = KEYVAL_ALTSPACE; const TCHAR szALTENTER[] = KEYVAL_ALTENTER; const TCHAR szWinLie[] = KEYVAL_WINLIE; const TCHAR szGlobalMem[] = KEYVAL_GLOBALMEM; const TCHAR szRealMode[] = KEYVAL_REALMODE; const TCHAR szMouse[] = KEYVAL_MOUSE; const TCHAR szEMS[] = KEYVAL_EMS; const TCHAR szCDROM[] = KEYVAL_CDROM; const TCHAR szNetwork[] = KEYVAL_NETWORK; const TCHAR szDiskLock[] = KEYVAL_DISKLOCK; const TCHAR szPrivateCFG[] = KEYVAL_PRIVATECFG; const TCHAR szCloseOnExit[] = KEYVAL_CLOSEONEXIT; const TCHAR szAllowSSaver[] = KEYVAL_ALLOWSSAVER; const TCHAR szUniqueSettings[] = KEYVAL_UNIQUESETTINGS;
const LPCTSTR apszKey[] = { szParams, szBatchFile, szLowMem, szEmsMem, szXmsMem, szDpmiMem, szEnable, szDisable, };
const LPCTSTR apszKeyVal[] = { szWindowed, // abKeyValIDBits[0]
szBackground, // abKeyValIDBits[1]
szExclusive, // abKeyValIDBits[2]
szDetectIdle, // abKeyValIDBits[3]
szLowLocked, // abKeyValIDBits[4]
szEMSLocked, // abKeyValIDBits[5]
szXMSLocked, // abKeyValIDBits[6]
szUseHMA, // abKeyValIDBits[7]
szEmulateROM, // abKeyValIDBits[8]
szRetainVRAM, // abKeyValIDBits[9]
szFastPaste, // abKeyValIDBits[10]
szALTTAB, // abKeyValIDBits[11]
szALTESC, // abKeyValIDBits[12]
szCTRLESC, // abKeyValIDBits[13]
szPRTSCRN, // abKeyValIDBits[14]
szALTPRTSCRN, // abKeyValIDBits[15]
szALTSPACE, // abKeyValIDBits[16]
szALTENTER, // abKeyValIDBits[17]
szWinLie, // abKeyValIDBits[18]
szGlobalMem, // abKeyValIDBits[19]
szRealMode, // abKeyValIDBits[20]
szMouse, // abRMKeyValIDBits[0]
szEMS, // abRMKeyValIDBits[1]
szCDROM, // abRMKeyValIDBits[2]
szNetwork, // abRMKeyValIDBits[3]
szDiskLock, // abRMKeyValIDBits[4]
szPrivateCFG, // abRMKeyValIDBits[5]
szCloseOnExit, // special case 0 (see "special case 0" below)
szAllowSSaver, // special case 1 (see "special case 1" below)
szUniqueSettings, // Never transferred to PIF - Used to populate registry
};
// Array of bit numbers that must be kept in sync with KEYVALIDs
//
// 0x80 means bit must be inverted
// 0x40 means bit must be set in PfW386Flags2 instead of PfW386Flags
const BYTE abKeyValIDBits[] = { BITNUM(fFullScreen) | 0x80, BITNUM(fBackground), BITNUM(fExclusive), BITNUM(fPollingDetect), BITNUM(fVMLocked), BITNUM(fEMSLocked), BITNUM(fXMSLocked), BITNUM(fNoHMA) | 0x80, BITNUM(fVidTxtEmulate) | 0x40, BITNUM(fVidRetainAllo) | 0x40, BITNUM(fINT16Paste), BITNUM(fALTTABdis) | 0x80, BITNUM(fALTESCdis) | 0x80, BITNUM(fCTRLESCdis) | 0x80, BITNUM(fPRTSCdis) | 0x80, BITNUM(fALTPRTSCdis) | 0x80, BITNUM(fALTSPACEdis) | 0x80, BITNUM(fALTENTERdis) | 0x80, BITNUM(fWinLie), BITNUM(fGlobalProtect), BITNUM(fRealMode), };
const BYTE abRMKeyValIDBits[] = { BITNUM(RMOPT_MOUSE), BITNUM(RMOPT_EMS), BITNUM(RMOPT_CDROM), BITNUM(RMOPT_NETWORK), BITNUM(RMOPT_DISKLOCK), BITNUM(RMOPT_PRIVATECFG), BITNUM(RMOPT_VESA), }; // FEATURE: other bits to be supported (maybe):
// WIN_TOOLBAR,
// WIN_SAVESETTINGS,
// MSE_WINDOWENABLE | 0x80,
// MSE_EXCLUSIVE,
// TSK_NOWARNTERMINATE | 0x80,
void InitWorkDir(PPROPLINK ppl, LPPROPPRG lpPrg, LPPROPNT40 lpnt40) { int i;
if (lpnt40) { lstrcpyn((LPTSTR)lpnt40->awchWorkDir, ppl->szPathName, min(ARRAYSIZE(lpnt40->awchWorkDir),ppl->iFileName+1));
// Working directories like C:\ are ok, but C:\FOO\ are not,
// so remove trailing '\' in that case
i = lstrlen((LPTSTR)lpnt40->awchWorkDir)-1; if (i > 2 && lpnt40->awchWorkDir[i] == TEXT('\\')) lpnt40->awchWorkDir[i] = TEXT('\0');
WideCharToMultiByte( CP_ACP, 0, (LPWSTR)lpnt40->awchWorkDir, -1, lpPrg->achWorkDir, ARRAYSIZE(lpPrg->achWorkDir), NULL, NULL ); } else { WideCharToMultiByte( CP_ACP, 0, ppl->szPathName, min(ARRAYSIZE(lpPrg->achWorkDir),ppl->iFileName+1), (LPSTR)lpPrg->achWorkDir, ARRAYSIZE(lpPrg->achWorkDir), NULL, NULL );
// Working directories like C:\ are ok, but C:\FOO\ are not,
// so remove trailing '\' in that case
i = lstrlenA(lpPrg->achWorkDir)-1; if (i > 2 && lpPrg->achWorkDir[i] == '\\') lpPrg->achWorkDir[i] = '\0'; } }
BOOL FAR GetAppsInfData(PPROPLINK ppl, LPPROPPRG lpPrg, LPPROPNT40 lpnt40, HINF hInf, LPCTSTR lpszApp, BOOL fNotAmbiguous, int flOpt) { HINF hinfApps; int id, i; TCHAR szTmp[MAX_PATH]; TCHAR szPIFSection[MAX_KEY_SIZE]; BOOL fSuccess = FALSE; INFCONTEXT InfContext; DWORD dwSize; FunctionName(GetAppsInfData);
//
// Although not strictly part of INF processing, it's most
// convenient here to search for any ICO file that might exist
// in the same directory as the app, and select it for our default icon.
//
lstrcpyn(szTmp, ppl->szPathName, ppl->iFileExt+1); lstrcpy(szTmp + ppl->iFileExt, TEXT(".ICO")); if ((int)GetFileAttributes(szTmp) != -1) { StringCchCopy((LPTSTR)lpnt40->awchIconFile, ARRAYSIZE(lpnt40->awchIconFile), szTmp); WideCharToMultiByte( CP_ACP, 0, (LPWSTR)lpnt40->awchIconFile, -1, lpPrg->achIconFile, ARRAYSIZE(lpPrg->achIconFile), NULL, NULL ); lpPrg->wIconIndex = 0; PifMgr_SetProperties(ppl, MAKELP(0,GROUP_PRG), lpPrg, SIZEOF(*lpPrg), SETPROPS_CACHE); PifMgr_SetProperties(ppl, MAKELP(0,GROUP_NT40), lpnt40, SIZEOF(*lpnt40), SETPROPS_CACHE); }
if (hInf) hinfApps = hInf; else hinfApps = SetupOpenInfFileW(LoadStringSafe(NULL, IDS_APPSINF, szTmp, ARRAYSIZE(szTmp)), 0, INF_STYLE_WIN4, NULL );
if (hinfApps==INVALID_HANDLE_VALUE) { id = IDS_CANTOPENAPPSINF; if (GetLastError()==ERROR_FILE_NOT_FOUND) id = IDS_NOAPPSINF; Warning((HWND)ppl, (WORD)id, MB_ICONEXCLAMATION | MB_OK | MB_NOFOCUS); goto CloseDLL; }
// OK, now we have APPS.INF open, so let's bounce around the [pif95]
// section and try to find the app of interest.
if (!SetupFindFirstLine(hinfApps, TEXT("pif95"), NULL, &InfContext)) { Warning((HWND)ppl, IDS_APPSINFERROR, MB_ICONEXCLAMATION | MB_OK | MB_NOFOCUS); goto CloseInf; }
// OK, we've found the [pif95] section, so let's go to it
do {
if (!SetupGetStringFieldW(&InfContext, APPSINF_FILENAME, szTmp, ARRAYSIZE(szTmp), &dwSize)) continue;
// We need to read the rest of the fields now, before we do any
// more processing, because otherwise we lose our place in the file
if (lstrcmpi(szTmp, ppl->szPathName+ppl->iFileName) == 0) {
// See if Other File was specified, and then make sure it
// exists. If it doesn't, then we need to continue the search.
// Initialize szTmp with only the path portion of the app's
// fully-qualified name. Giving lstrcpyn a length of iFileName+1
// insures that szTmp[ppl->iFileName] will be NULL.
lstrcpyn(szTmp, ppl->szPathName, ppl->iFileName+1);
SetupGetStringFieldW(&InfContext, APPSINF_OTHERFILE, &szTmp[ppl->iFileName], ARRAYSIZE(lpPrg->achOtherFile), &dwSize);
// If szTmp[ppl->iFileName] is no longer NULL, then
// GetStringField filled it in. See if the file exists.
if (szTmp[ppl->iFileName]) { if ((int)GetFileAttributes(szTmp) == -1) continue; // Other File didn't exist, continue search
}
// If the PIF data we have is ambiguous, and it has already
// been initialized with data from this APPS.INF entry, then just
// leave the PIF data alone and LEAVE.
if (lpPrg->flPrgInit & PRGINIT_AMBIGUOUSPIF) {
if (lstrcmpi((LPWSTR)lpnt40->awchOtherFile, szTmp+ppl->iFileName) == 0) {
if (!szTmp[ppl->iFileName]) {
// The comparison was inconclusive; both filenames
// are blank. See if the filename contained in
// lpPrg->achCmdLine matches lpszApp; if not, again
// we should fail the search.
//
// It's ok to whack lpPrg->achCmdLine with a null;
// OpenProperties (our only caller) doesn't depend on
// that data in lpPrg.
lpnt40->awchCmdLine[lstrskipfnameA(lpPrg->achCmdLine)] = L'\0';
if (lstrcmpi((LPWSTR)lpnt40->awchCmdLine, lpszApp) != 0)
goto CloseInf; // unsuccessful search
} fSuccess++; // successful search
}
// Otherwise, this APPS.INF entry isn't a match, implying
// some of the PIF's settings don't really apply. We need
// to fail this search, get back to OpenProperties, look ONLY
// for _DEFAULT.PIF, and let it try to call GetAppsInfData
// one more time.
goto CloseInf; }
// Otherwise, update Other File. THIS is the APPS.INF entry
// we're going to use!
StringCchCopy((LPWSTR)lpnt40->awchOtherFile, ARRAYSIZE(lpnt40->awchOtherFile), szTmp + ppl->iFileName); WideCharToMultiByte( CP_ACP, 0, (LPWSTR)lpnt40->awchOtherFile, -1, lpPrg->achOtherFile, ARRAYSIZE( lpPrg->achOtherFile ), NULL, NULL );
SetupGetStringFieldW(&InfContext, APPSINF_TITLE, (LPWSTR)lpnt40->awchTitle, ARRAYSIZE(lpnt40->awchTitle), &dwSize); WideCharToMultiByte( CP_ACP, 0, (LPWSTR)lpnt40->awchTitle, -1, lpPrg->achTitle, ARRAYSIZE( lpPrg->achTitle ), NULL, NULL );
StringCchCopy((LPWSTR)lpnt40->awchCmdLine, ARRAYSIZE(lpnt40->awchCmdLine), lpszApp); WideCharToMultiByte( CP_ACP, 0, (LPWSTR)lpnt40->awchCmdLine, -1, lpPrg->achCmdLine, ARRAYSIZE( lpPrg->achCmdLine ), NULL, NULL );
i = 0; SetupGetIntField(&InfContext, APPSINF_NOWORKDIR, &i);
// Only set the working directory if "NoWorkDir" in the INF
// is FALSE and no working directory was supplied by the caller.
if (i == 0 && !lpnt40->awchWorkDir[0]) { // No hard-coded working directory, so let's provide one
InitWorkDir(ppl, lpPrg, lpnt40); }
szTmp[0] = 0; SetupGetStringFieldW(&InfContext, APPSINF_ICONFILE, szTmp, ARRAYSIZE(szTmp), &dwSize);
if (!szTmp[0]) StringCchCopy(szTmp, ARRAYSIZE(szTmp), TEXT("SHELL32.DLL"));
i = 0; SetupGetIntField(&InfContext, APPSINF_ICONINDEX, &i);
// Update the icon info now, if it's valid
if (i != 0) { StringCchCopy((LPWSTR)lpnt40->awchIconFile, ARRAYSIZE(lpnt40->awchIconFile), szTmp); WideCharToMultiByte( CP_ACP, 0, (LPWSTR)lpnt40->awchIconFile, -1, lpPrg->achIconFile, ARRAYSIZE( lpPrg->achIconFile ), NULL, NULL ); lpPrg->wIconIndex = (WORD) i; }
SetupGetStringFieldW(&InfContext, APPSINF_SECTIONID, szPIFSection, ARRAYSIZE(szPIFSection), &dwSize);
szTmp[0] = TEXT('\0'); SetupGetStringFieldW(&InfContext, APPSINF_NOPIF, szTmp, ARRAYSIZE(szTmp), &dwSize);
// This code used to set INHBITPIF if the app was NOT on a
// fixed disk, knowing that we would otherwise try to create
// a PIF in the PIF directory instead of the app's directory;
// in other words, NOPIF really meant "no PIF in the PIF
// directory please, because this app is ambiguously named".
// Now, we want to always allow PIF creation, so the user
// always has a place to save properties for an app. But we
// also need to propagate the old NOPIF flag to AMBIGUOUSPIF,
// so that we'll always check to see if the PIF should be
// regenerated (based on the presence of a NEW Other File).
lpPrg->flPrgInit &= ~PRGINIT_AMBIGUOUSPIF; if (!fNotAmbiguous && szTmp[0] == TEXT('1')) lpPrg->flPrgInit |= PRGINIT_AMBIGUOUSPIF;
if (flOpt & OPENPROPS_FORCEREALMODE) lpPrg->flPrgInit |= PRGINIT_REALMODE;
// Time to dirty those properties!
PifMgr_SetProperties(ppl, MAKELP(0,GROUP_PRG), lpPrg, SIZEOF(*lpPrg), SETPROPS_CACHE); PifMgr_SetProperties(ppl, MAKELP(0,GROUP_NT40), lpnt40, SIZEOF(*lpnt40), SETPROPS_CACHE);
GetAppsInfSectionData(&InfContext, APPSINF_DEFAULT_SECTION, ppl);
if (*szPIFSection) GetAppsInfSectionData(&InfContext, szPIFSection, ppl);
// Make a note that we found INF settings (appwiz cares)
ppl->flProp |= PROP_INFSETTINGS;
// GetAppsInfSectionData affects program props, so get fresh copy
PifMgr_GetProperties(ppl, MAKELP(0,GROUP_PRG), lpPrg, SIZEOF(*lpPrg), GETPROPS_NONE);
// Now call appwiz in "silent configuration mode", to create the
// per-app config and autoexec images, if app runs in real mode;
// BUT don't do this if the caller (NOT the INF) specified no PIF,
// to avoid unwanted dialog boxes popping up from appwiz. Yes, I'm
// telling appwiz to be quiet, but sometimes he just can't contain
// himself (ie, silent configuration may not be possible given the
// the real-mode configuration required).
if (!(ppl->flProp & PROP_INHIBITPIF)) { if (lpPrg->flPrgInit & PRGINIT_REALMODE) AppWizard(NULL, ppl, WIZACTION_SILENTCONFIGPROP); } FlushPIFData(ppl, FALSE);
fSuccess++; // successful search
goto CloseInf; }
} while (SetupFindNextLine(&InfContext, &InfContext));
CloseInf: if (!hInf) SetupCloseInfFile(hinfApps);
CloseDLL: return fSuccess; }
void GetAppsInfSectionData(PINFCONTEXT pInfContext, LPCTSTR lpszSection, PPROPLINK ppl) { int i, j, idKey; LPSTDPIF lpstd; LPW386PIF30 lp386; LPWENHPIF40 lpenh; TCHAR szVal[MAX_KEYVAL_SIZE]; TCHAR szVal2[MAX_KEYVAL_SIZE]; FunctionName(GetAppsInfSectionData);
if (!SetupFindFirstLineW(pInfContext, lpszSection, NULL, NULL)) return;
ppl->cLocks++;
lpstd = (LPSTDPIF)ppl->lpPIFData;
// lp386 may or may not exist, but we'll create if not
lp386 = GetGroupData(ppl, szW386HDRSIG30, NULL, NULL); if (!lp386) { if (AddGroupData(ppl, szW386HDRSIG30, NULL, SIZEOF(W386PIF30))) { lp386 = GetGroupData(ppl, szW386HDRSIG30, NULL, NULL); if (!lp386) goto UnlockPIF; } }
// lpenh may or may not exist, but we'll create if not
lpenh = GetGroupData(ppl, szWENHHDRSIG40, NULL, NULL); if (!lpenh) { if (AddGroupData(ppl, szWENHHDRSIG40, NULL, SIZEOF(WENHPIF40))) { lpenh = GetGroupData(ppl, szWENHHDRSIG40, NULL, NULL); if (!lpenh) goto UnlockPIF; } }
do { BYTE bInvert; DWORD dwSize;
idKey = GetKeyID(pInfContext);
if (!SetupGetStringFieldW(pInfContext, APPSINF_KEYVAL, szVal, ARRAYSIZE(szVal), &dwSize)) continue;
szVal2[0] = TEXT('\0'); if (idKey >= KEYID_LOWMEM && idKey <= KEYID_DPMIMEM) SetupGetStringFieldW(pInfContext, APPSINF_KEYVAL2, szVal2, ARRAYSIZE(szVal2), &dwSize);
bInvert = 0;
switch (idKey) { case KEYID_UNKNOWN: ASSERTFAIL(); break;
case KEYID_NONE: break;
case KEYID_PARAMS: { WCHAR szTmp[ ARRAYSIZE(lp386->PfW386params) ];
MultiByteToWideChar( CP_ACP, 0, (LPSTR)lp386->PfW386params, -1, szTmp, ARRAYSIZE(szTmp) ); SetupGetStringFieldW(pInfContext, APPSINF_KEYVAL, szTmp, SIZEOF(lp386->PfW386params), &dwSize); }
break;
case KEYID_BATCHFILE: break;
case KEYID_LOWMEM: if (!lstrcmpi(szVal, g_szAuto)) lp386->PfW386minmem = 0xFFFF; else lp386->PfW386minmem = (WORD) StrToInt(szVal);
if (!szVal2[0]) lp386->PfW386maxmem = 0xFFFF; else lp386->PfW386maxmem = (WORD) StrToInt(szVal2); break;
case KEYID_EMSMEM: if (!lstrcmpi(szVal, g_szNone)) { lp386->PfMaxEMMK = lp386->PfMinEMMK = 0; } if (!lstrcmpi(szVal, g_szAuto)) { lp386->PfMinEMMK = 0; lp386->PfMaxEMMK = 0xFFFF; } else lp386->PfMaxEMMK = lp386->PfMinEMMK = (WORD) StrToInt(szVal);
if (szVal2[0]) lp386->PfMaxEMMK = (WORD) StrToInt(szVal2); break;
case KEYID_XMSMEM: if (!lstrcmpi(szVal, g_szNone)) { lp386->PfMaxXmsK = lp386->PfMinXmsK = 0; } if (!lstrcmpi(szVal, g_szAuto)) { lp386->PfMinXmsK = 0; lp386->PfMaxXmsK = 0xFFFF; } else lp386->PfMaxXmsK = lp386->PfMinXmsK = (WORD) StrToInt(szVal);
if (szVal2[0]) lp386->PfMaxXmsK = (WORD) StrToInt(szVal2); break;
case KEYID_DPMIMEM: if (!lstrcmpi(szVal, g_szAuto)) lpenh->envProp.wMaxDPMI = 0; else lpenh->envProp.wMaxDPMI = (WORD) StrToInt(szVal); break;
case KEYID_DISABLE: bInvert = 0x80; // fall into KEYID_ENABLE...
case KEYID_ENABLE: for (i=1; 0 != (j = GetKeyValID(pInfContext, i)); i++) { int s; BYTE b;
if (j == KEYVAL_ID_UNKNOWN) { ASSERTFAIL(); continue; }
if (j == KEYVAL_ID_UNIQUESETTINGS) { continue; }
j--;
if (j < ARRAYSIZE(abKeyValIDBits)) {
b = abKeyValIDBits[j];
s = b & 0x3F; b ^= bInvert; if (!(b & 0x80)) { if (!(b & 0x40)) { lp386->PfW386Flags |= 1L << s; } else lp386->PfW386Flags2 |= 1L << s; } else { if (!(b & 0x40)) lp386->PfW386Flags &= ~(1L << s); else lp386->PfW386Flags2 &= ~(1L << s); } } else { j -= ARRAYSIZE(abKeyValIDBits);
if (j < ARRAYSIZE(abRMKeyValIDBits)) {
b = abRMKeyValIDBits[j];
s = b & 0x3F; b ^= bInvert;
if (!(b & 0x80)) lpenh->dwRealModeFlagsProp |= 1L << s; else lpenh->dwRealModeFlagsProp &= ~(1L << s); } else { j -= ARRAYSIZE(abRMKeyValIDBits);
switch(j) { case 0: // special case 0
if (!bInvert) lpstd->MSflags |= EXITMASK; else lpstd->MSflags &= ~EXITMASK; break;
case 1: // special case 1
if (bInvert) lpenh->tskProp.flTsk |= TSK_NOSCREENSAVER; else lpenh->tskProp.flTsk &= ~TSK_NOSCREENSAVER; break;
default: ASSERTFAIL(); break; } } } } break; } } while (SetupFindNextLine(pInfContext, pInfContext));
UnlockPIF: ppl->cLocks--;
}
int GetKeyID(PINFCONTEXT pInfContext) { int i; TCHAR szCurKey[MAX_KEY_SIZE]; DWORD dwSize; FunctionName(GetKeyID);
if (SetupGetStringFieldW(pInfContext, APPSINF_KEY, szCurKey, ARRAYSIZE(szCurKey), &dwSize)) { for (i=0; i<ARRAYSIZE(apszKey); i++) { if (!lstrcmpi(szCurKey, apszKey[i])) return i+1; } return KEYID_UNKNOWN; } return KEYID_NONE; }
int GetKeyValID(PINFCONTEXT pInfContext, int i) { TCHAR szCurKeyVal[MAX_KEYVAL_SIZE]; DWORD dwSize; FunctionName(GetKeyValID);
if (SetupGetStringFieldW(pInfContext, i, szCurKeyVal, ARRAYSIZE(szCurKeyVal), &dwSize)) { for (i=0; i<ARRAYSIZE(apszKeyVal); i++) { if (!lstrcmpi(szCurKeyVal, apszKeyVal[i])) return i+1; } return KEYVAL_ID_UNKNOWN; } return KEYVAL_ID_NONE; }
#endif
|