200 lines
7.2 KiB
C
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;
|
|
}
|