|
|
/*----------------------------------------------------------------------------
/ 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; }
|