windows-nt/Source/XPSP1/NT/shell/shell32/cabstate.c
2020-09-26 16:20:57 +08:00

200 lines
7.2 KiB
C

/*----------------------------------------------------------------------------
/ Title;
/ cabstate.c => cabinet state i/o
/
/ Purpose:
/ Provides a clean API to fill out the cabinet state from the registry, if the
/ relevent keys cannot be found then we set the relevant defaults. This is
/ called by the explorer.
/
/ History:
/ 23apr96 daviddv New API which passes the structure size in
/ 18mar96 daviddv Bug fix; Added colour state to FALSE when state structure not read
/ 7feb96 daviddv Tweeked cabinet state writing
/ 30jan96 daviddv Created
/
/----------------------------------------------------------------------------*/
#include "shellprv.h"
#include "regstr.h"
#include "cstrings.h"
#pragma hdrstop
TCHAR const c_szCabinetState[] = REGSTR_PATH_EXPLORER TEXT( "\\CabinetState");
TCHAR const c_szSettings[] = TEXT("Settings");
TCHAR const c_szFullPath[] = TEXT("FullPath");
/*----------------------------------------------------------------------------
/ Read in the CABINETSTATE structure from the registry and attempt to validate it.
/
/ Notes:
/ -
/
/ In:
/ lpCabinetState => pointer to CABINETSTATE structure to be filled.
/ cLength = size of structure to be filled
/
/ Out:
/ [lpState] filled in with data
/ fReadFromRegistry == indicates if the structure was actually read from the registry
/ or if we are giviing the client a default one.
/----------------------------------------------------------------------------*/
STDAPI_(BOOL) ReadCabinetState( CABINETSTATE *lpState, int cLength )
{
DWORD cbData = SIZEOF(CABINETSTATE);
BOOL fReadFromRegistry = FALSE;
CABINETSTATE state;
SHELLSTATE ss;
DWORD dwType;
HKEY hKey;
ASSERT( lpState );
SHGetSetSettings(&ss, SSF_WIN95CLASSIC, FALSE);
if ( lpState && cLength )
{
BOOL fReadFullPath = FALSE;
//
// Setup the default state of the structure and read in the current state
// from the registry (over our freshly initialised structure).
//
state.cLength = SIZEOF(CABINETSTATE);
state.nVersion = CABINETSTATE_VERSION;
state.fSimpleDefault = TRUE;
state.fFullPathTitle = FALSE;
state.fSaveLocalView = TRUE;
state.fNotShell = FALSE;
state.fNewWindowMode = BOOLIFY(ss.fWin95Classic);
state.fShowCompColor = FALSE;
state.fDontPrettyNames = FALSE;
state.fAdminsCreateCommonGroups = TRUE;
state.fUnusedFlags = 0;
state.fMenuEnumFilter = SHCONTF_FOLDERS | SHCONTF_NONFOLDERS;
if ( !GetSystemMetrics( SM_CLEANBOOT ) &&
ERROR_SUCCESS == RegOpenKeyEx( HKEY_CURRENT_USER, c_szCabinetState, 0L, KEY_READ, &hKey ) )
{
DWORD dwFullPath=0;
DWORD cbFullPath=SIZEOF(dwFullPath);
fReadFromRegistry = ( ERROR_SUCCESS == SHQueryValueEx( hKey,
c_szSettings,
NULL,
&dwType,
(PVOID) &state, &cbData ) );
if (ERROR_SUCCESS == SHQueryValueEx(hKey, c_szFullPath, NULL, NULL, (LPVOID)&dwFullPath, &cbFullPath))
{
fReadFullPath = TRUE;
state.fFullPathTitle = (BOOL)dwFullPath ? TRUE : FALSE;
}
RegCloseKey( hKey );
}
//
// Fix the structure if it is an early version and write back into the registry
// to avoid having to do it again.
//
if ( fReadFromRegistry && state.nVersion < CABINETSTATE_VERSION )
{
// NT4 and IE4x had the same value for state.nVersion (1), and we have to stomp some of the flags
// depending on whether we are pre-IE4x or not. To differentiate, we see if c_szFullPath was present.
// This reg key was introduced only in IE40.
if ( (state.nVersion < 1) || ((state.nVersion == 1) && !fReadFullPath) )
{
state.fNewWindowMode = BOOLIFY(ss.fWin95Classic);
state.fAdminsCreateCommonGroups = TRUE; // Moved post BETA 2 SUR!
state.fUnusedFlags = 0;
state.fMenuEnumFilter = SHCONTF_FOLDERS | SHCONTF_NONFOLDERS;
}
state.cLength = SIZEOF(CABINETSTATE);
state.nVersion = CABINETSTATE_VERSION;
WriteCabinetState( &state );
}
//
// Copy only the requested data back to the caller.
//
state.cLength = (int) min( SIZEOF(CABINETSTATE), cLength );
memcpy( lpState, &state, cLength );
}
return fReadFromRegistry;
}
// old export
STDAPI_(BOOL) OldReadCabinetState( LPCABINETSTATE lpState, int cLength )
{
return ReadCabinetState(lpState, sizeof(CABINETSTATE));
}
/*----------------------------------------------------------------------------
/ Writes a CABINETSTATE structure back into the registry.
/
/ Notes:
/ Attempt to do the right thing when given a small structure to write
/ back so that we don't mess up the users settings.
/
/ In:
/ lpState -> structure to be written
/
/ Out:
/ fSuccess = TRUE / FALSE indicating if state has been seralised
/----------------------------------------------------------------------------*/
STDAPI_(BOOL) WriteCabinetState(CABINETSTATE *lpState)
{
BOOL fSuccess = FALSE;
if (lpState)
{
CABINETSTATE state;
HKEY hKey;
// Check to see if the structure is the right size, if its too small
// then we must merge it with a real one before writing back!
if (lpState->cLength < SIZEOF(CABINETSTATE))
{
ReadCabinetState(&state, SIZEOF(state));
memcpy(&state, lpState, lpState->cLength);
state.cLength = SIZEOF(CABINETSTATE);
lpState = &state;
}
if ( ERROR_SUCCESS == RegCreateKey( HKEY_CURRENT_USER, c_szCabinetState, &hKey ) )
{
DWORD dwFullPath = lpState->fFullPathTitle ? TRUE : FALSE;
fSuccess = ERROR_SUCCESS == RegSetValueEx( hKey,
c_szSettings,
0,
REG_BINARY,
(LPVOID)lpState, (DWORD)SIZEOF(CABINETSTATE) );
// NOTE: We have to continue writing this key. One of the uses for it is to decide
// whether we are pre-IE4 or not. See ReadCabinetState()...
RegSetValueEx(hKey, c_szFullPath, 0, REG_DWORD, (LPVOID)&dwFullPath, sizeof(dwFullPath));
RegCloseKey( hKey );
}
}
if (fSuccess)
{
// Notify anybody who is listening
HANDLE hChange = SHGlobalCounterCreate(&GUID_FolderSettingsChange);
SHGlobalCounterIncrement(hChange);
SHGlobalCounterDestroy(hChange);
}
return fSuccess;
}