windows-nt/Source/XPSP1/NT/ds/security/gina/policy/poledit/load.c

897 lines
27 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
//*********************************************************************
//* Microsoft Windows **
//* Copyright(c) Microsoft Corp., 1993 **
//*********************************************************************
#include "admincfg.h"
UINT LoadUsersFromKey(HWND hwndList,HKEY hkeyRoot,TABLEENTRY * pTableEntry,
DWORD dwType);
UINT LoadOneEntry(USERDATA ** ppUserData,TABLEENTRY * pTableEntry,HKEY hkeyRoot,
TCHAR * pszCurrentKeyName,HGLOBAL hUser,DWORD *pdwFoundSettings);
UINT LoadUserData(USERDATA ** ppUserData,HGLOBAL hTable,HKEY hkeyRoot,
TCHAR * pszCurrentKeyName,HGLOBAL hUser,DWORD *pdwFoundSettings);
UINT LoadPolicy(USERDATA ** ppUserData,TABLEENTRY * pTableEntry,HKEY hkeyRoot,
TCHAR * pszCurrentKeyName,HGLOBAL hUser);
UINT LoadSettings(USERDATA ** ppUserData,TABLEENTRY * pTableEntry,HKEY hkeyRoot,
TCHAR * pszCurrentKeyName,HGLOBAL hUser,DWORD *pdwFoundSettings);
UINT LoadListboxData(USERDATA ** ppUserData,TABLEENTRY * pTableEntry,HKEY hkeyRoot,
TCHAR * pszCurrentKeyName,HGLOBAL hUser,DWORD * pdwFound);
BOOL ReadStandardValue(HKEY hkeyRoot,TCHAR * pszKeyName,TCHAR * pszValueName,
TABLEENTRY * pTableEntry,DWORD * pdwData,DWORD * pdwFound);
BOOL ReadCustomValue(HKEY hkeyRoot,TCHAR * pszKeyName,TCHAR * pszValueName,
TCHAR * pszValue,UINT cbValue,DWORD * pdwValue,DWORD * pdwFlags);
BOOL CompareCustomValue(HKEY hkeyRoot,TCHAR * pszKeyName,TCHAR * pszValueName,
STATEVALUE * pStateValue,DWORD * pdwFound);
// flags for detected settings
#define FS_PRESENT 0x0001
#define FS_DELETED 0x0002
/*******************************************************************
NAME: LoadFile
SYNOPSIS: Loads the specified policy file
********************************************************************/
BOOL LoadFile(TCHAR * pszFilename,HWND hwndApp,HWND hwndList,BOOL fDisplayErrors)
{
HKEY hkeyMain=NULL,hkeyUser=NULL,hkeyWorkstation=NULL,hkeyGroup=NULL,hkeyGroupPriority=NULL;
UINT uRet;
OFSTRUCT of;
HCURSOR hOldCursor;
HFILE hFile;
of.cBytes = sizeof(of);
hOldCursor=SetCursor(LoadCursor(NULL,IDC_WAIT));
// RegLoadKey returns totally coarse error codes, so first do
// an open file on the file to get a sane error message if there's
// a problem
hFile = OpenFile(pszFilename,&of,OF_EXIST);
if (hFile == HFILE_ERROR) {
SetCursor(hOldCursor);
if (fDisplayErrors)
DisplayStandardError(hwndApp,pszFilename,IDS_ErrREGERR_LOADKEY1,
of.nErrCode);
return FALSE;
}
// Not needed. This will raise an exception.
// _lclose (hFile);
// load the hive file
if ((uRet = MyRegLoadKey(HKEY_LOCAL_MACHINE,szTMPDATA,pszFilename))
!= ERROR_SUCCESS) {
SetCursor(hOldCursor);
if (fDisplayErrors)
DisplayStandardError(hwndApp,pszFilename,IDS_ErrREGERR_LOADKEY1,uRet);
return FALSE;
}
// read information from local registry
if ( (RegOpenKey(HKEY_LOCAL_MACHINE,szTMPDATA,&hkeyMain) !=
ERROR_SUCCESS) ||
(RegOpenKey(hkeyMain,szUSERS,&hkeyUser) != ERROR_SUCCESS) ||
(RegOpenKey(hkeyMain,szWORKSTATIONS,&hkeyWorkstation)
!= ERROR_SUCCESS)) {
SetCursor(hOldCursor);
if (fDisplayErrors)
MsgBoxParam(hwndApp,IDS_ErrINVALIDPOLICYFILE,pszFilename,
MB_ICONEXCLAMATION,MB_OK);
if (hkeyWorkstation) RegCloseKey(hkeyWorkstation);
if (hkeyUser) RegCloseKey(hkeyUser);
if (hkeyMain) RegCloseKey(hkeyMain);
MyRegUnLoadKey(HKEY_LOCAL_MACHINE,szTMPDATA);
return FALSE;
}
// if we fail to open these two keys no big deal, these are optional keys.
// HKEYs are checked below before we use them
RegOpenKey(hkeyMain,szUSERGROUPS,&hkeyGroup);
RegOpenKey(hkeyMain,szUSERGROUPDATA,&hkeyGroupPriority);
// load users
if ((uRet = LoadUsersFromKey(hwndList,hkeyUser,gClassList.pUserCategoryList,
UT_USER)) != ERROR_SUCCESS)
goto cleanup;
// load workstations
if ((uRet = LoadUsersFromKey(hwndList,hkeyWorkstation,gClassList.pMachineCategoryList,
UT_MACHINE))
!= ERROR_SUCCESS)
goto cleanup;
#ifdef INCL_GROUP_SUPPORT
// load groups
if (hkeyGroupPriority && hkeyGroup) {
if ((uRet = LoadGroupPriorityList(hkeyGroupPriority,hkeyGroup)) != ERROR_SUCCESS)
goto cleanup;
if (uRet = LoadUsersFromKey(hwndList,hkeyGroup,gClassList.pUserCategoryList,
UT_USER | UF_GROUP)
!= ERROR_SUCCESS)
goto cleanup;
}
#endif
uRet = ERROR_SUCCESS;
cleanup:
RegCloseKey(hkeyUser);
RegCloseKey(hkeyWorkstation);
RegCloseKey(hkeyMain);
if (hkeyGroup)
RegCloseKey(hkeyGroup);
if (hkeyGroupPriority)
RegCloseKey(hkeyGroupPriority);
MyRegUnLoadKey(HKEY_LOCAL_MACHINE,szTMPDATA);
SetFileAttributes(pszFilename,FILE_ATTRIBUTE_ARCHIVE);
ClearDeletedUserList();
SetCursor(hOldCursor);
if (uRet != ERROR_SUCCESS && fDisplayErrors) {
if (uRet == ERROR_NOT_ENOUGH_MEMORY) {
MsgBox(hwndApp,IDS_ErrOUTOFMEMORY,MB_ICONEXCLAMATION,MB_OK);
} else {
TCHAR szFmt[REGBUFLEN],szMsg[REGBUFLEN+MAX_PATH+1];
LoadSz(IDS_ErrREGERR_LOADKEY,szFmt,ARRAYSIZE(szFmt));
wsprintf(szMsg,szFmt,pszFilename,uRet);
MsgBoxSz(hwndApp,szMsg,MB_ICONEXCLAMATION,MB_OK);
}
// remove any users that might have gotten loaded
RemoveAllUsers(hwndList);
}
return (uRet == ERROR_SUCCESS);
}
/*******************************************************************
NAME: LoadFromRegistry
SYNOPSIS: Loads policies from the registry
NOTES: Errors will be displayed if fDisplayErrors is TRUE.
********************************************************************/
BOOL LoadFromRegistry(HWND hwndApp,HWND hwndList,BOOL fDisplayErrors)
{
HKEY hkeyUser=NULL,hkeyWorkstation=NULL;
UINT uRet = ERROR_SUCCESS;
HGLOBAL hUser,hWorkstation;
USERDATA * pUserData=NULL,* pWorkstationData=NULL;
HCURSOR hOldCursor;
if ((RegOpenKeyEx(hkeyVirtHCU,NULL,0,KEY_ALL_ACCESS,&hkeyUser) != ERROR_SUCCESS) ||
(RegOpenKeyEx(hkeyVirtHLM,NULL,0,KEY_ALL_ACCESS,&hkeyWorkstation) != ERROR_SUCCESS)) {
if (fDisplayErrors)
MsgBox(hwndApp,IDS_ErrCANTOPENREGISTRY,MB_ICONEXCLAMATION,MB_OK);
if (hkeyUser) RegCloseKey(hkeyUser);
if (hkeyWorkstation) RegCloseKey(hkeyWorkstation);
return FALSE;
}
hUser = AddUser(hwndList,LoadSz(IDS_LOCALUSER,szSmallBuf,ARRAYSIZE(szSmallBuf))
,UT_USER);
hWorkstation = AddUser(hwndList,LoadSz(IDS_LOCALCOMPUTER,szSmallBuf,
ARRAYSIZE(szSmallBuf)),UT_MACHINE);
if (!hUser || !hWorkstation || !(pUserData = (USERDATA *) GlobalLock(hUser)) ||
!(pWorkstationData = (USERDATA *) GlobalLock(hWorkstation)) ) {
uRet = ERROR_NOT_ENOUGH_MEMORY;
}
hOldCursor=SetCursor(LoadCursor(NULL,IDC_WAIT));
if (uRet == ERROR_SUCCESS)
uRet = LoadUserData(&pUserData,gClassList.pUserCategoryList,hkeyUser,NULL,
hUser,NULL);
if (uRet == ERROR_SUCCESS)
uRet = LoadUserData(&pWorkstationData,gClassList.pMachineCategoryList,
hkeyWorkstation,NULL,hWorkstation,NULL);
RegCloseKey(hkeyUser);
RegCloseKey(hkeyWorkstation);
GlobalUnlock(hUser);
GlobalUnlock(hWorkstation);
SetCursor(hOldCursor);
if (uRet != ERROR_SUCCESS) {
if (uRet == ERROR_NOT_ENOUGH_MEMORY) {
if (fDisplayErrors)
MsgBox(hwndApp,IDS_ErrOUTOFMEMORY,MB_ICONEXCLAMATION,MB_OK);
} else {
TCHAR szMsg[REGBUFLEN+1];
wsprintf(szMsg,TEXT("%lu"),uRet);
if (fDisplayErrors)
MsgBoxParam(hwndApp,IDS_ErrREGERR_LOAD,szMsg,MB_ICONEXCLAMATION,MB_OK);
}
RemoveAllUsers(hwndList);
return FALSE;
}
ClearDeletedUserList();
return TRUE;
}
UINT LoadUsersFromKey(HWND hwndList,HKEY hkeyRoot,TABLEENTRY * pTableEntry,
DWORD dwType)
{
TCHAR szKeyName[MAX_PATH+1];
UINT uRet,nIndex=0;
HGLOBAL hUser;
USERDATA * pUserData;
HKEY hKey;
TCHAR szUnmappedName[MAXNAMELEN+1];
do {
// enumerate the subkeys, which will be user/workstation names
if ((uRet=RegEnumKey(hkeyRoot,nIndex,szKeyName,ARRAYSIZE(szKeyName)))
== ERROR_SUCCESS) {
// open the subkey
if ((uRet = RegOpenKey(hkeyRoot,szKeyName,&hKey)) != ERROR_SUCCESS)
return uRet;
// allocate this user and add to list control
UnmapUserName(szKeyName,szUnmappedName,(BOOL) (dwType & UT_USER));
hUser = AddUser(hwndList,szUnmappedName,dwType);
if ( !hUser || !(pUserData = (USERDATA *) GlobalLock(hUser))) {
RegCloseKey(hKey);
return ERROR_NOT_ENOUGH_MEMORY;
}
// load user data into user's buffer
uRet=LoadUserData(&pUserData,pTableEntry,hKey,NULL,hUser,NULL);
#ifdef INCL_GROUP_SUPPORT
// add group name to bottom of priority list. The group name
// should already be somewhere on priority list because we loaded
// the list earlier, but this will add the group name to the bottom
// of the list if it's not on the list already. Adds extra robustness
// in the face of god-knows-whose-app creating flaky policy files.
if (dwType == (UT_USER | UF_GROUP))
AddGroupPriEntry(szUnmappedName);
#endif
RegCloseKey(hKey);
GlobalUnlock(hUser);
// make a copy of the initial state of each user, so on
// a save we only have to save the deltas. We need to only
// save the deltas, because saves have to be non-destructive--
// we can't clean the user's tree out and start over because
// there might be stuff in there we don't know about.
CloneUser(hUser);
if (uRet != ERROR_SUCCESS) return uRet;
}
nIndex++;
} while (uRet == ERROR_SUCCESS);
// end of enum will report ERROR_NO_MORE_ITEMS, don't report this as error
if (uRet == ERROR_NO_MORE_ITEMS) uRet = ERROR_SUCCESS;
return uRet;
}
UINT LoadUserData(USERDATA ** ppUserData,TABLEENTRY * pTableEntry,HKEY hkeyRoot,
TCHAR * pszCurrentKeyName,HGLOBAL hUser,DWORD *pdwFoundSettings)
{
UINT uRet=ERROR_SUCCESS;
while (pTableEntry && (uRet == ERROR_SUCCESS)) {
uRet = LoadOneEntry(ppUserData,pTableEntry,hkeyRoot,
pszCurrentKeyName,hUser,pdwFoundSettings);
pTableEntry = pTableEntry->pNext;
}
return uRet;
}
UINT LoadOneEntry(USERDATA ** ppUserData,TABLEENTRY * pTableEntry,HKEY hkeyRoot,
TCHAR * pszCurrentKeyName,HGLOBAL hUser,DWORD *pdwFoundSettings)
{
UINT uRet;
#if 0
wsprintf(szDebugOut,TEXT("LoadOneEntry: %s\r\n"),GETNAMEPTR(pTableEntry));
OutputDebugString(szDebugOut);
#endif
// if there is a key name for this entry, it becomes the "current"
// key name-- it will be overridden if child entries specify their
// own keys, otherwise it's the default key for children to use
if (pTableEntry->uOffsetKeyName) {
pszCurrentKeyName = GETKEYNAMEPTR(pTableEntry);
}
if ((pTableEntry->dwType == ETYPE_CATEGORY || pTableEntry->dwType
== ETYPE_ROOT) &&
(pTableEntry->pChild)) {
// if entry is a category, recusively process sub-categories and policies
if ((uRet=LoadUserData(ppUserData,pTableEntry->pChild,
hkeyRoot,pszCurrentKeyName,hUser,pdwFoundSettings)) != ERROR_SUCCESS) {
return uRet;
}
} else if (pTableEntry->dwType == ETYPE_POLICY) {
if ((uRet = LoadPolicy(ppUserData,pTableEntry,hkeyRoot,
pszCurrentKeyName,hUser)) != ERROR_SUCCESS) {
return uRet;
}
} else if ( (pTableEntry->dwType & ETYPE_MASK) == ETYPE_SETTING
&& !(pTableEntry->dwType & STYPE_TEXT)) {
if ((uRet = LoadSettings(ppUserData,pTableEntry,hkeyRoot,
pszCurrentKeyName,hUser,pdwFoundSettings)) != ERROR_SUCCESS) {
return uRet;
}
}
return ERROR_SUCCESS;
}
UINT LoadPolicy(USERDATA ** ppUserData,TABLEENTRY * pTableEntry,HKEY hkeyRoot,
TCHAR * pszCurrentKeyName,HGLOBAL hUser)
{
DWORD dwData=0;
UINT uRet;
TCHAR * pszValueName;
DWORD dwFoundSettings=0;
BOOL fHasPolicySwitch=FALSE;
BOOL fFound=FALSE,fCustomOn=FALSE,fCustomOff=FALSE;
// get the name of the value to read, if any
if (((POLICY *) pTableEntry)->uOffsetValueName) {
fHasPolicySwitch = TRUE;
pszValueName = GETVALUENAMEPTR(((POLICY *) pTableEntry));
// first look for custom on/off values
if (((POLICY *) pTableEntry)->uOffsetValue_On) {
fCustomOn = TRUE;
if (CompareCustomValue(hkeyRoot,pszCurrentKeyName,pszValueName,
(STATEVALUE *) ((TCHAR *) pTableEntry + ((POLICY *)
pTableEntry)->uOffsetValue_On),&dwFoundSettings)) {
dwData = 1;
fFound = TRUE;
}
}
if (!fFound && ((POLICY *) pTableEntry)->uOffsetValue_Off) {
fCustomOff = TRUE;
if (CompareCustomValue(hkeyRoot,pszCurrentKeyName,pszValueName,
(STATEVALUE *) ((TCHAR *) pTableEntry + ((POLICY *)
pTableEntry)->uOffsetValue_Off),&dwFoundSettings)) {
dwData = 0;
fFound = TRUE;
}
}
// look for standard values if custom values have not been specified
if (!fCustomOn && !fCustomOff &&
ReadStandardValue(hkeyRoot,pszCurrentKeyName,pszValueName,
pTableEntry,&dwData,&dwFoundSettings)) {
fFound = TRUE;
}
if (fFound) {
// store data in user's buffer
(*ppUserData)->SettingData[((POLICY *) pTableEntry)->uDataIndex].uData =
(dwData ? IMG_CHECKED : IMG_UNCHECKED);
}
}
dwFoundSettings = 0;
// process settings underneath this policy (if any)
if (pTableEntry->pChild && (dwData || !fHasPolicySwitch)) {
if ((uRet=LoadUserData(ppUserData,pTableEntry->pChild,hkeyRoot,
pszCurrentKeyName,hUser,&dwFoundSettings)) !=ERROR_SUCCESS) {
return uRet;
}
}
if (!fHasPolicySwitch) {
// store data in user's buffer
if (dwFoundSettings) {
(*ppUserData)->SettingData[((POLICY *) pTableEntry)->uDataIndex].uData =
(dwFoundSettings & FS_PRESENT ? IMG_CHECKED : IMG_UNCHECKED);
}
}
return ERROR_SUCCESS;
}
UINT LoadSettings(USERDATA ** ppUserData,TABLEENTRY * pTableEntry,HKEY hkeyRoot,
TCHAR * pszCurrentKeyName,HGLOBAL hUser,DWORD * pdwFound)
{
UINT uRet = ERROR_SUCCESS;
TCHAR * pszValueName = NULL;
DWORD dwData,dwFlags,dwFoundSettings=0;
TCHAR szData[MAXSTRLEN];
BOOL fCustomOn=FALSE,fCustomOff=FALSE,fFound=FALSE;
TCHAR * pObjectData = GETOBJECTDATAPTR(((SETTINGS *)pTableEntry));
TCHAR szNewValueName[MAX_PATH+1];
// get the name of the value to read
if (((SETTINGS *) pTableEntry)->uOffsetValueName) {
pszValueName = GETVALUENAMEPTR(((SETTINGS *) pTableEntry));
}
else return ERROR_NOT_ENOUGH_MEMORY;
switch (pTableEntry->dwType & STYPE_MASK) {
case STYPE_EDITTEXT:
case STYPE_COMBOBOX:
dwFlags = ( (SETTINGS *) pTableEntry)->dwFlags;
// add prefixes if appropriate
PrependValueName(pszValueName,dwFlags,
szNewValueName,ARRAYSIZE(szNewValueName));
if ((uRet = ReadRegistryStringValue(hkeyRoot,pszCurrentKeyName,
szNewValueName,szData,ARRAYSIZE(szData) * sizeof(TCHAR))) == ERROR_SUCCESS) {
GlobalUnlock(hUser);
if (!SetVariableLengthData(hUser,((SETTINGS *)
pTableEntry)->uDataIndex,szData,lstrlen(szData)+1)) {
return ERROR_NOT_ENOUGH_MEMORY;
}
if (!((*ppUserData) = (USERDATA *) GlobalLock(hUser)))
return ERROR_NOT_ENOUGH_MEMORY;
// set flag that we found setting in registry/policy file
if (pdwFound)
*pdwFound |= FS_PRESENT;
} else if ((dwAppState & AS_POLICYFILE) && !(dwFlags & VF_DELETE)) {
// see if this key is marked as deleted
PrependValueName(pszValueName,VF_DELETE,
szNewValueName,ARRAYSIZE(szNewValueName));
if ((uRet = ReadRegistryStringValue(hkeyRoot,pszCurrentKeyName,
szNewValueName,szData,ARRAYSIZE(szData) * sizeof(TCHAR))) == ERROR_SUCCESS) {
// set flag that we found setting marked as deleted in
// policy file
if (pdwFound)
*pdwFound |= FS_DELETED;
}
}
return ERROR_SUCCESS;
break;
case STYPE_CHECKBOX:
// first look for custom on/off values
if (((CHECKBOXINFO *) pObjectData)->uOffsetValue_On) {
fCustomOn = TRUE;
if (CompareCustomValue(hkeyRoot,pszCurrentKeyName,pszValueName,
(STATEVALUE *) ((TCHAR *) pTableEntry + ((CHECKBOXINFO *)
pObjectData)->uOffsetValue_On),&dwFoundSettings)) {
dwData = 1;
fFound = TRUE;
}
}
if (!fFound && ((CHECKBOXINFO *) pObjectData)->uOffsetValue_Off) {
fCustomOff = TRUE;
if (CompareCustomValue(hkeyRoot,pszCurrentKeyName,pszValueName,
(STATEVALUE *) ((TCHAR *) pTableEntry + ((CHECKBOXINFO *)
pObjectData)->uOffsetValue_Off),&dwFoundSettings)) {
dwData = 0;
fFound = TRUE;
}
}
// look for standard values if custom values have not been specified
if (!fFound &&
ReadStandardValue(hkeyRoot,pszCurrentKeyName,pszValueName,
pTableEntry,&dwData,&dwFoundSettings)) {
fFound = TRUE;
}
if (fFound) {
(*ppUserData)->SettingData[((SETTINGS *)
pTableEntry)->uDataIndex].uData = dwData;
// set flag that we found setting in registry
if (pdwFound)
*pdwFound |= dwFoundSettings;
}
return ERROR_SUCCESS;
break;
case STYPE_NUMERIC:
if (ReadStandardValue(hkeyRoot,pszCurrentKeyName,pszValueName,
pTableEntry,&dwData,&dwFoundSettings)) {
(*ppUserData)->SettingData[((SETTINGS *)
pTableEntry)->uDataIndex].uData = dwData;
// set flag that we found setting in registry
if (pdwFound)
*pdwFound |= dwFoundSettings;
}
break;
case STYPE_DROPDOWNLIST:
if (ReadCustomValue(hkeyRoot,pszCurrentKeyName,pszValueName,
szData,ARRAYSIZE(szData) * sizeof(TCHAR),&dwData,&dwFlags)) {
BOOL fMatch = FALSE;
if ((dwAppState & AS_POLICYFILE) &&
(dwFlags & VF_DELETE)) {
// set flag that we found setting marked as deleted
// in policy file
if (pdwFound)
*pdwFound |= FS_DELETED;
return ERROR_SUCCESS;
}
// walk the list of DROPDOWNINFO structs (one for each state),
// and see if the value we found matches the value for the state
if ( ((SETTINGS *) pTableEntry)->uOffsetObjectData) {
DROPDOWNINFO * pddi = (DROPDOWNINFO *)
GETOBJECTDATAPTR( ((SETTINGS *) pTableEntry));
UINT nIndex = 0;
do {
if (dwFlags == pddi->dwFlags) {
if (pddi->dwFlags & VF_ISNUMERIC) {
if (dwData == pddi->dwValue)
fMatch = TRUE;
} else if (!pddi->dwFlags) {
if (!lstrcmpi(szData,(TCHAR *) pTableEntry +
pddi->uOffsetValue))
fMatch = TRUE;
}
}
if (!pddi->uOffsetNextDropdowninfo || fMatch)
break;
pddi = (DROPDOWNINFO *) ( (TCHAR *) pTableEntry +
pddi->uOffsetNextDropdowninfo);
nIndex++;
} while (!fMatch);
if (fMatch) {
(*ppUserData)->SettingData[((SETTINGS *)
pTableEntry)->uDataIndex].uData = nIndex;
// set flag that we found setting in registry
if (pdwFound)
*pdwFound |= FS_PRESENT;
}
}
}
break;
case STYPE_LISTBOX:
return LoadListboxData(ppUserData,pTableEntry,hkeyRoot,
pszCurrentKeyName,hUser,pdwFound);
break;
}
return ERROR_SUCCESS;
}
/*******************************************************************
NAME: ReadCustomValue
SYNOPSIS: For specified keyname and value name, retrieve the
value (if there is one).
NOTES: fills in pszValue if value is REG_SZ, fills in *pdwValue
if value is REG_DWORD (and sets VF_ISNUMERIC). Sets
VF_DELETE if value is marked for deletion.
********************************************************************/
BOOL ReadCustomValue(HKEY hkeyRoot,TCHAR * pszKeyName,TCHAR * pszValueName,
TCHAR * pszValue,UINT cbValue,DWORD * pdwValue,DWORD * pdwFlags)
{
HKEY hKey;
DWORD dwType,dwSize=cbValue * sizeof(TCHAR);
BOOL fSuccess = FALSE;
TCHAR szNewValueName[MAX_PATH+1];
*( (DWORD *)pszValue) = *pdwValue=0;
if (RegOpenKey(hkeyRoot,pszKeyName,&hKey) == ERROR_SUCCESS) {
if (RegQueryValueEx(hKey,pszValueName,NULL,&dwType,(LPBYTE) pszValue,
&dwSize) == ERROR_SUCCESS) {
if (dwType == REG_SZ) {
// value returned in pszValueName
*pdwFlags = 0;
fSuccess = TRUE;
} else if (dwType == REG_DWORD || dwType == REG_BINARY) {
// copy value to *pdwValue
memcpy(pdwValue,pszValue,sizeof(DWORD));
*pdwFlags = VF_ISNUMERIC;
fSuccess = TRUE;
}
} else {
// see if this is a value that's marked for deletion
// (valuename is prepended with "**del."
PrependValueName(pszValueName,VF_DELETE,
szNewValueName,ARRAYSIZE(szNewValueName));
if (RegQueryValueEx(hKey,szNewValueName,NULL,&dwType,(LPBYTE) pszValue,
&dwSize) == ERROR_SUCCESS) {
fSuccess=TRUE;
*pdwFlags = VF_DELETE;
} else {
// see if this is a soft value
// (valuename is prepended with "**soft."
PrependValueName(pszValueName,VF_SOFT,
szNewValueName,ARRAYSIZE(szNewValueName));
if (RegQueryValueEx(hKey,szNewValueName,NULL,&dwType,(LPBYTE) pszValue,
&dwSize) == ERROR_SUCCESS) {
fSuccess=TRUE;
*pdwFlags = VF_SOFT;
}
}
}
RegCloseKey(hKey);
}
return fSuccess;
}
BOOL CompareCustomValue(HKEY hkeyRoot,TCHAR * pszKeyName,TCHAR * pszValueName,
STATEVALUE * pStateValue,DWORD * pdwFound)
{
TCHAR szValue[MAXSTRLEN];
DWORD dwValue;
TCHAR szNewValueName[MAX_PATH+1];
// add prefixes if appropriate
PrependValueName(pszValueName,pStateValue->dwFlags,
szNewValueName,ARRAYSIZE(szNewValueName));
if (pStateValue->dwFlags & VF_ISNUMERIC) {
if ((ReadRegistryDWordValue(hkeyRoot,pszKeyName,
szNewValueName,&dwValue) == ERROR_SUCCESS) &&
dwValue == pStateValue->dwValue) {
*pdwFound = FS_PRESENT;
return TRUE;
}
} else if (pStateValue->dwFlags & VF_DELETE) {
if (dwAppState & AS_POLICYFILE) {
// see if this is a value that's marked for deletion
// (valuename is prepended with "**del."
if ((ReadRegistryStringValue(hkeyRoot,pszKeyName,
szNewValueName,szValue,ARRAYSIZE(szValue) * sizeof(TCHAR))) == ERROR_SUCCESS) {
*pdwFound = FS_DELETED;
return TRUE;
}
} else {
// return TRUE if value ISN't there...
if (ReadRegistryDWordValue(hkeyRoot,pszKeyName,
szNewValueName,&dwValue) != ERROR_SUCCESS) {
*pdwFound = FS_DELETED;
return TRUE;
}
}
} else {
if ((ReadRegistryStringValue(hkeyRoot,pszKeyName,
szNewValueName,szValue,ARRAYSIZE(szValue) * sizeof(TCHAR))) == ERROR_SUCCESS &&
!lstrcmpi(szValue,pStateValue->szValue)) {
*pdwFound = FS_PRESENT;
return TRUE;
}
}
return FALSE;
}
BOOL ReadStandardValue(HKEY hkeyRoot,TCHAR * pszKeyName,TCHAR * pszValueName,
TABLEENTRY * pTableEntry,DWORD * pdwData,DWORD * pdwFound)
{
UINT uRet;
TCHAR szNewValueName[MAX_PATH+1];
// add prefixes if appropriate
PrependValueName(pszValueName,((SETTINGS *) pTableEntry)->dwFlags,
szNewValueName,ARRAYSIZE(szNewValueName));
if ( ((SETTINGS *) pTableEntry)->dwFlags & DF_TXTCONVERT) {
// read numeric value as text if specified
TCHAR szNum[11];
uRet = ReadRegistryStringValue(hkeyRoot,pszKeyName,
szNewValueName,szNum,ARRAYSIZE(szNum) * sizeof(TCHAR));
if (uRet == ERROR_SUCCESS) {
StringToNum(szNum,pdwData);
*pdwFound = FS_PRESENT;
return TRUE;
}
} else {
// read numeric value as binary
uRet = ReadRegistryDWordValue(hkeyRoot,pszKeyName,
szNewValueName,pdwData);
if (uRet == ERROR_SUCCESS) {
*pdwFound = FS_PRESENT;
return TRUE;
}
}
// see if this settings has been marked as 'deleted'
if ((dwAppState & AS_POLICYFILE) && !(dwCmdLineFlags & CLF_DIALOGMODE)) {
TCHAR szVal[MAX_PATH+1];
*pdwData = 0;
PrependValueName(pszValueName,VF_DELETE,szNewValueName,
ARRAYSIZE(szNewValueName));
uRet=ReadRegistryStringValue(hkeyRoot,pszKeyName,
szNewValueName,szVal,ARRAYSIZE(szVal) * sizeof(TCHAR));
if (uRet == ERROR_SUCCESS) {
*pdwFound = FS_DELETED;
return TRUE;
}
}
return FALSE;
}
UINT LoadListboxData(USERDATA ** ppUserData,TABLEENTRY * pTableEntry,HKEY hkeyRoot,
TCHAR * pszCurrentKeyName,HGLOBAL hUser,DWORD * pdwFound)
{
HKEY hKey;
UINT nIndex=0,nLen;
TCHAR szValueName[MAX_PATH+1],szValueData[MAX_PATH+1];
DWORD cbValueName,cbValueData;
DWORD dwType,dwAlloc=1024,dwUsed=0;
HGLOBAL hBuf;
TCHAR * pBuf;
SETTINGS * pSettings = (SETTINGS *) pTableEntry;
LISTBOXINFO * pListboxInfo = (LISTBOXINFO *)
GETOBJECTDATAPTR(pSettings);
BOOL fFoundValues=FALSE,fFoundDelvals=FALSE;
UINT uRet=ERROR_SUCCESS;
if (RegOpenKey(hkeyRoot,pszCurrentKeyName,&hKey) != ERROR_SUCCESS)
return ERROR_SUCCESS; // nothing to do
// allocate a temp buffer to read entries into
if (!(hBuf = GlobalAlloc(GHND,dwAlloc * sizeof(TCHAR))) ||
!(pBuf = (TCHAR *) GlobalLock(hBuf))) {
if (hBuf)
GlobalFree(hBuf);
return ERROR_NOT_ENOUGH_MEMORY;
}
while (TRUE) {
cbValueName=ARRAYSIZE(szValueName);
cbValueData=ARRAYSIZE(szValueData) * sizeof(TCHAR);
uRet=RegEnumValue(hKey,nIndex,szValueName,&cbValueName,NULL,
&dwType,szValueData,&cbValueData);
// stop if we're out of items
if (uRet != ERROR_SUCCESS && uRet != ERROR_MORE_DATA)
break;
nIndex++;
// if valuename prefixed with '**', it's a control code, ignore it
if (szValueName[0] == TEXT('*') && szValueName[1] == TEXT('*')) {
// if we found **delvals., then some sort of listbox stuff
// is going on, remember that we found this code
if (!lstrcmpi(szValueName,szDELVALS))
fFoundDelvals = TRUE;
continue;
}
// only process this item if enum was successful
// (so we'll skip items with weird errors like ERROR_MORE_DATA and
// but keep going with the enum)
if (uRet == ERROR_SUCCESS) {
TCHAR * pszData;
// if there's no value name prefix scheme specified (e.g.
// value names are "foo1", "foo2", etc), and the explicit valuename
// flag isn't set where we remember the value name as well as
// the data for every value, then we need the value name to
// be the same as the value data ("thing.exe=thing.exe").
if (!(pSettings->dwFlags & DF_EXPLICITVALNAME) &&
!(pListboxInfo->uOffsetPrefix) && !(pListboxInfo->uOffsetValue)) {
if (dwType != REG_SZ || lstrcmpi(szValueName,szValueData))
continue; // skip this value if val name != val data
}
// if explicit valuenames used, then copy the value name into
// buffer
if (pSettings->dwFlags & DF_EXPLICITVALNAME) {
nLen = lstrlen(szValueName) + 1;
if (!(pBuf=ResizeBuffer(pBuf,hBuf,dwUsed+nLen+4,&dwAlloc)))
return ERROR_NOT_ENOUGH_MEMORY;
lstrcpy(pBuf+dwUsed,szValueName);
dwUsed += nLen;
}
// for default listbox type, value data is the actual "data"
// and value name either will be the same as the data or
// some prefix + "1", "2", etc. If there's a data value to
// write for each entry, then the "data" is the value name
// (e.g. "Larry = foo", "Dave = foo"), etc. If explicit value names
// are turned on, then both the value name and data are stored
// and editable
// copy value data into buffer
if (pListboxInfo->uOffsetValue) {
// data value set, use value name for data
pszData = szValueName;
} else pszData = szValueData;
nLen = lstrlen(pszData) + 1;
if (!(pBuf=ResizeBuffer(pBuf,hBuf,dwUsed+nLen+4,&dwAlloc)))
return ERROR_NOT_ENOUGH_MEMORY;
lstrcpy(pBuf+dwUsed,pszData);
dwUsed += nLen;
fFoundValues=TRUE;
}
}
// doubly null-terminate the buffer... safe to do this because we
// tacked on the extra "+4" in the ResizeBuffer calls above
*(pBuf+dwUsed) = TEXT('\0');
dwUsed++;
uRet = ERROR_SUCCESS;
if (fFoundValues) {
// add the value data to user's buffer
GlobalUnlock(hUser);
if (!SetVariableLengthData(hUser,((SETTINGS *)
pTableEntry)->uDataIndex,pBuf,dwUsed)) {
uRet = ERROR_NOT_ENOUGH_MEMORY;
} else if (!((*ppUserData) = (USERDATA *) GlobalLock(hUser)))
uRet = ERROR_NOT_ENOUGH_MEMORY;
// set flag that we found setting in registry/policy file
if (pdwFound)
*pdwFound |= FS_PRESENT;
} else {
if (fFoundDelvals && pdwFound) {
*pdwFound |= FS_DELETED;
}
}
GlobalUnlock(hBuf);
GlobalFree(hBuf);
RegCloseKey(hKey);
return uRet;
}