897 lines
27 KiB
C
897 lines
27 KiB
C
//*********************************************************************
|
|
//* 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;
|
|
}
|