1684 lines
36 KiB
C
1684 lines
36 KiB
C
|
|
||
|
/*++
|
||
|
|
||
|
Copyright (c) 1999 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
iniact.c
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
This module contains the implementation of the engine and actions on INI files.
|
||
|
To add a new INI action, just add it to wkstamig.inf or usermig.inf, add it to
|
||
|
INI_ACTIONS macro list and implement a function with the same name having
|
||
|
FNINIACT prototype.
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Ovidiu Temereanca (ovidiut) 07-May-1999
|
||
|
|
||
|
Environment:
|
||
|
|
||
|
GUI mode Setup.
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
07-May-1999 ovidiut Creation and initial implementation.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
|
||
|
//
|
||
|
// includes
|
||
|
//
|
||
|
#include "pch.h"
|
||
|
#include "migmainp.h"
|
||
|
|
||
|
|
||
|
#ifdef DEBUG
|
||
|
#define DBG_INIACT "IniAct"
|
||
|
#endif
|
||
|
|
||
|
//
|
||
|
// GUID Format: {%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}
|
||
|
// we care about the exact length of this string
|
||
|
//
|
||
|
#define GUIDSTR_LEN (1 + 8 + 1 + 4 + 1 + 4 + 1 + 4 + 1 + 12 + 1)
|
||
|
#define DASH_INDEXES 1+8, 1+8+1+4, 1+8+1+4+1+4, 1+8+1+4+1+4+1+4
|
||
|
|
||
|
//
|
||
|
// Add a macro here with an INI Action function name and implement it.
|
||
|
// Make sure wkstamig.inf or usermig.inf use the same function name in [INI Files Actions].
|
||
|
// See FNINIACT definition for the function prototype
|
||
|
//
|
||
|
#define INI_ACTIONS \
|
||
|
DEFMAC (MigrateDesktopIniSCI) \
|
||
|
DEFMAC (MigrateDesktopIniESFV) \
|
||
|
|
||
|
//
|
||
|
// Private prototypes
|
||
|
//
|
||
|
|
||
|
//
|
||
|
// description of rule's settings
|
||
|
//
|
||
|
typedef struct {
|
||
|
//
|
||
|
// INI file specification, as appears in INF files (Field 1)
|
||
|
//
|
||
|
PCTSTR IniSpec;
|
||
|
//
|
||
|
// Section specified in INF (Field 2)
|
||
|
//
|
||
|
PCTSTR Section;
|
||
|
//
|
||
|
// Key specified in INF (Field 3)
|
||
|
//
|
||
|
PCTSTR Key;
|
||
|
//
|
||
|
// Data specified in INF (Field 4)
|
||
|
//
|
||
|
PCTSTR Data;
|
||
|
//
|
||
|
// Function-dependent strings defined in INF;
|
||
|
// all strings from section named in Field 5
|
||
|
// the strings are double-zero terminated
|
||
|
//
|
||
|
GROWBUFFER Settings;
|
||
|
} RULEATTRIBS, *PRULEATTRIBS;
|
||
|
|
||
|
|
||
|
//
|
||
|
// description of an INI file (original, actual, NT location)
|
||
|
//
|
||
|
typedef struct {
|
||
|
//
|
||
|
// original (Win9x) INI file location
|
||
|
//
|
||
|
PCTSTR OrigIniPath;
|
||
|
//
|
||
|
// actual INI file location (it was copied to a temp location)
|
||
|
//
|
||
|
PCTSTR ActualLocation;
|
||
|
//
|
||
|
// NT file location; it may be different than Win9x location
|
||
|
//
|
||
|
PCTSTR NtIniPath;
|
||
|
} INIFILE, *PINIFILE;
|
||
|
|
||
|
|
||
|
//
|
||
|
// the prototype of an INI file processing function
|
||
|
//
|
||
|
typedef BOOL (FNINIACT) (
|
||
|
IN PRULEATTRIBS RuleAttribs,
|
||
|
IN PINIFILE IniFile
|
||
|
);
|
||
|
|
||
|
typedef FNINIACT* PFNINIACT;
|
||
|
|
||
|
|
||
|
//
|
||
|
// description of an INI action (there is a list of actions)
|
||
|
//
|
||
|
typedef struct _INIACT {
|
||
|
//
|
||
|
// it's a list of actions
|
||
|
//
|
||
|
struct _INIACT* Next;
|
||
|
//
|
||
|
// processing function name (Key field in INF)
|
||
|
//
|
||
|
PCTSTR FnName;
|
||
|
//
|
||
|
// a pointer to the processing function
|
||
|
//
|
||
|
PFNINIACT FnIniAct;
|
||
|
//
|
||
|
// the attributes of this rule as defined in INF + context
|
||
|
//
|
||
|
RULEATTRIBS RuleAttribs;
|
||
|
} INIACT, *PINIACT;
|
||
|
|
||
|
|
||
|
//
|
||
|
// this serves as a map from function name to function pointer
|
||
|
//
|
||
|
typedef struct {
|
||
|
PCTSTR FnName;
|
||
|
PFNINIACT Fn;
|
||
|
} INIACTMAP, *PINIACTMAP;
|
||
|
|
||
|
|
||
|
//
|
||
|
// global data
|
||
|
//
|
||
|
|
||
|
//
|
||
|
// memory pool used by IniActions
|
||
|
//
|
||
|
static POOLHANDLE g_IniActPool = NULL;
|
||
|
//
|
||
|
// the list of rules
|
||
|
//
|
||
|
static PINIACT g_IniActHead = NULL, g_IniActTail = NULL;
|
||
|
|
||
|
//
|
||
|
// function declarations
|
||
|
//
|
||
|
#define DEFMAC(Name) FNINIACT Name;
|
||
|
|
||
|
INI_ACTIONS
|
||
|
|
||
|
#undef DEFMAC
|
||
|
|
||
|
//
|
||
|
// map function name -> function pointer
|
||
|
//
|
||
|
#define DEFMAC(Name) TEXT(#Name), Name,
|
||
|
|
||
|
static INIACTMAP g_IniActionsMapping[] = {
|
||
|
INI_ACTIONS
|
||
|
NULL, NULL
|
||
|
};
|
||
|
|
||
|
#undef DEFMAC
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
pLookupRuleFn (
|
||
|
IN OUT PINIACT IniAct
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
pLookupRuleFn tries to find the function specified in IniAct->FnName and put the pointer
|
||
|
in IniAct->FnIniAct. It will look in the global map g_IniActionsMapping.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
IniAct - Specifies the function name and receives the function pointer.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
TRUE if the function was found, FALSE otherwise
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
INT i;
|
||
|
|
||
|
for (i = 0; g_IniActionsMapping[i].FnName; i++) {
|
||
|
if (StringMatch (g_IniActionsMapping[i].FnName, IniAct->FnName)) {
|
||
|
IniAct->FnIniAct = g_IniActionsMapping[i].Fn;
|
||
|
return TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
PCTSTR
|
||
|
pGetNextMultiSzString (
|
||
|
IN PCTSTR Str
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
pGetNextMultiSzString skips over the string specified to get to the next string,
|
||
|
assumed to be in contiguous memory.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Str - Specifies the string to skip over
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
A pointer to the caracter following the string (starting of the next one).
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
return (PCTSTR) (((PBYTE)Str) + SizeOfString (Str));
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
pGetRuleSectionSettings (
|
||
|
IN OUT PINIACT IniAct,
|
||
|
IN HINF Inf,
|
||
|
IN PCTSTR Section
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
pGetRuleSectionSettings reads all settings from specified Inf file and
|
||
|
specified section and appends them to IniAct->RuleAttribs.Settings
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
IniAct - Receives the strings read
|
||
|
|
||
|
Inf - Specifies the source INF file
|
||
|
|
||
|
Section - Specifies the section containing the strings
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
none
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
INFCONTEXT ctx;
|
||
|
TCHAR field[MEMDB_MAX];
|
||
|
|
||
|
if (SetupFindFirstLine (Inf, Section, NULL, &ctx)) {
|
||
|
do {
|
||
|
if (SetupGetStringField (&ctx, 0, field, MEMDB_MAX, NULL)) {
|
||
|
MultiSzAppend (&IniAct->RuleAttribs.Settings, field);
|
||
|
}
|
||
|
} while (SetupFindNextLine (&ctx, &ctx));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
pGetIniActData (
|
||
|
IN OUT PINFCONTEXT ctx,
|
||
|
OUT PINIACT IniAct
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
pGetIniActData reads all rule settings from the specified INF context
|
||
|
and puts them in IniAct
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
ctx - Specifies the INF context containing the attributes of this rule;
|
||
|
receives new context data
|
||
|
|
||
|
IniAct - Receives the data read
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
TRUE if attributes read are valid and they make up a valid rule
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
TCHAR field[MEMDB_MAX];
|
||
|
TCHAR FileSpec[MAX_PATH];
|
||
|
|
||
|
if (!(SetupGetStringField (ctx, 0, field, MEMDB_MAX, NULL) && field[0])) {
|
||
|
DEBUGMSG ((
|
||
|
DBG_ASSERT,
|
||
|
"pGetIniActData: couldn't get function name in Wkstamig.inf"
|
||
|
));
|
||
|
MYASSERT (FALSE);
|
||
|
return FALSE;
|
||
|
}
|
||
|
IniAct->FnName = DuplicateText (field);
|
||
|
|
||
|
//
|
||
|
// lookup handling function
|
||
|
//
|
||
|
if (!pLookupRuleFn (IniAct)) {
|
||
|
DEBUGMSG ((
|
||
|
DBG_ASSERT,
|
||
|
"pGetIniActData: couldn't find implementation of function [%s] in Wkstamig.inf",
|
||
|
IniAct->FnName
|
||
|
));
|
||
|
MYASSERT (FALSE);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (!(SetupGetStringField (ctx, 1, field, MEMDB_MAX, NULL) && field[0])) {
|
||
|
DEBUGMSG ((
|
||
|
DBG_ASSERT,
|
||
|
"pGetIniActData: couldn't get INI file spec in Wkstamig.inf"
|
||
|
));
|
||
|
MYASSERT (FALSE);
|
||
|
return FALSE;
|
||
|
}
|
||
|
//
|
||
|
// expand env vars first
|
||
|
//
|
||
|
if (ExpandEnvironmentStrings (field, FileSpec, MAX_PATH) <= MAX_PATH) {
|
||
|
//
|
||
|
// there shouldn't be any % left
|
||
|
//
|
||
|
if (_tcschr (FileSpec, TEXT('%'))) {
|
||
|
DEBUGMSG ((
|
||
|
DBG_ASSERT,
|
||
|
"pGetIniActData: invalid INI file spec in Wkstamig.inf"
|
||
|
));
|
||
|
MYASSERT (FALSE);
|
||
|
return FALSE;
|
||
|
}
|
||
|
} else {
|
||
|
DEBUGMSG ((
|
||
|
DBG_ASSERT,
|
||
|
"pGetIniActData: INI file spec too long in Wkstamig.inf"
|
||
|
));
|
||
|
MYASSERT (FALSE);
|
||
|
return FALSE;
|
||
|
}
|
||
|
IniAct->RuleAttribs.IniSpec = DuplicateText (FileSpec);
|
||
|
|
||
|
//
|
||
|
// rest of fields are optional
|
||
|
//
|
||
|
if (SetupGetStringField (ctx, 2, field, MEMDB_MAX, NULL) && field[0]) {
|
||
|
IniAct->RuleAttribs.Section = DuplicateText (field);
|
||
|
}
|
||
|
|
||
|
if (SetupGetStringField (ctx, 3, field, MEMDB_MAX, NULL) && field[0]) {
|
||
|
IniAct->RuleAttribs.Key = DuplicateText (field);
|
||
|
}
|
||
|
|
||
|
if (SetupGetStringField (ctx, 4, field, MEMDB_MAX, NULL) && field[0]) {
|
||
|
IniAct->RuleAttribs.Data = DuplicateText (field);
|
||
|
}
|
||
|
|
||
|
if (SetupGetStringField (ctx, 5, field, MEMDB_MAX, NULL) && field[0]) {
|
||
|
//
|
||
|
// this is actually a section name in the same INF file
|
||
|
// read its contents and make a multisz string with them
|
||
|
//
|
||
|
pGetRuleSectionSettings (IniAct, ctx->Inf, field);
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
pCleanUpIniAction (
|
||
|
IN OUT PINIACT IniAct
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
pCleanUpIniAction frees all resources associated with the given IniAct
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
IniAct - Specifies the action to be "emptied"; all resources are freed
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
none
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
FreeText (IniAct->FnName);
|
||
|
IniAct->FnName = NULL;
|
||
|
|
||
|
FreeText (IniAct->RuleAttribs.IniSpec);
|
||
|
FreeText (IniAct->RuleAttribs.Section);
|
||
|
FreeText (IniAct->RuleAttribs.Key);
|
||
|
FreeText (IniAct->RuleAttribs.Data);
|
||
|
FreeGrowBuffer (&IniAct->RuleAttribs.Settings);
|
||
|
ZeroMemory (&IniAct->RuleAttribs, sizeof (IniAct->RuleAttribs));
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
pCreateIniActions (
|
||
|
IN INIACT_CONTEXT Context
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
pCreateIniActions will create a list of rules read from an INF depending on the Context
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Context - Specifies the context in which the function is called
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
TRUE if the list (defined by the globals g_IniActHead and g_IniActTail) is not empty
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
INFCONTEXT InfContext;
|
||
|
PINIACT IniAct;
|
||
|
PCTSTR Section;
|
||
|
|
||
|
if (g_WkstaMigInf == INVALID_HANDLE_VALUE) {
|
||
|
DEBUGMSG ((DBG_ERROR, "Ini Actions: wkstamig.inf is not loaded"));
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (Context == INIACT_WKS_FIRST) {
|
||
|
Section = S_INIFILES_ACTIONS_FIRST;
|
||
|
} else {
|
||
|
Section = S_INIFILES_ACTIONS_LAST;
|
||
|
}
|
||
|
|
||
|
if (SetupFindFirstLine (g_WkstaMigInf, Section, NULL, &InfContext)) {
|
||
|
do {
|
||
|
IniAct = PoolMemGetMemory (g_IniActPool, sizeof (*IniAct));
|
||
|
ZeroMemory (IniAct, sizeof (*IniAct));
|
||
|
|
||
|
if (pGetIniActData (&InfContext, IniAct)) {
|
||
|
//
|
||
|
// add it to the list
|
||
|
//
|
||
|
if (g_IniActTail) {
|
||
|
g_IniActTail->Next = IniAct;
|
||
|
g_IniActTail = IniAct;
|
||
|
} else {
|
||
|
g_IniActHead = g_IniActTail = IniAct;
|
||
|
}
|
||
|
} else {
|
||
|
pCleanUpIniAction (IniAct);
|
||
|
PoolMemReleaseMemory (g_IniActPool, IniAct);
|
||
|
}
|
||
|
|
||
|
} while (SetupFindNextLine (&InfContext, &InfContext));
|
||
|
}
|
||
|
|
||
|
return g_IniActHead != NULL;
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
pFreeIniActions (
|
||
|
VOID
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
pFreeIniActions destroys all rules in the global list (see g_IniActHead and g_IniActTail)
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
none
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
none
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
PINIACT NextRule;
|
||
|
|
||
|
while (g_IniActHead) {
|
||
|
NextRule = g_IniActHead->Next;
|
||
|
pCleanUpIniAction (g_IniActHead);
|
||
|
PoolMemReleaseMemory (g_IniActPool, g_IniActHead);
|
||
|
g_IniActHead = NextRule;
|
||
|
}
|
||
|
g_IniActTail = NULL;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
pEnumFirstIniAction (
|
||
|
OUT PINIACT* IniAct
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
pEnumFirstIniAction enumerates the first rule in the global list and puts a pointer to it
|
||
|
in IniAct
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
IniAct - Receives the first INI rule; NULL if none
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
TRUE if there is at least a rule, FALSE if list is empty
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
*IniAct = g_IniActHead;
|
||
|
return *IniAct != NULL;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
pEnumNextIniAction (
|
||
|
IN OUT PINIACT* IniAct
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
pEnumNextIniAction enumerates the next action after IniAct in the global list and puts
|
||
|
a pointer to it in the same IniAct
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
IniAct - Specifies a pointer to an INI rule; will receive a pointer to the next rule;
|
||
|
receives NULL if last rule
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
TRUE if there is a rule following (*IniAct is a valid pointer), FALSE if not
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
if (*IniAct) {
|
||
|
*IniAct = (*IniAct)->Next;
|
||
|
}
|
||
|
return *IniAct != NULL;
|
||
|
}
|
||
|
|
||
|
|
||
|
PTSTR
|
||
|
pGetAllKeys (
|
||
|
IN PCTSTR IniFilePath,
|
||
|
IN PCTSTR Section
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
pGetAllKeys reads all keys or sections from the specified INI file and returns
|
||
|
a pointer to allocated memory that contains all keys in the specified section.
|
||
|
If section is NULL, a list of all sections is retrived instead.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
IniFilePath - Specifies the INI file
|
||
|
|
||
|
Section - Specifies the section containg the keys; if NULL, sections are retrieved
|
||
|
instead of keys
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
A pointer to a multisz containing all keys or sections; caller must free the memory
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
PTSTR Keys = NULL;
|
||
|
DWORD Size = 64 * sizeof (TCHAR);
|
||
|
DWORD chars;
|
||
|
|
||
|
MYASSERT (IniFilePath);
|
||
|
do {
|
||
|
if (Keys) {
|
||
|
PoolMemReleaseMemory (g_IniActPool, Keys);
|
||
|
}
|
||
|
Size *= 2;
|
||
|
Keys = PoolMemGetMemory (g_IniActPool, Size);
|
||
|
chars = GetPrivateProfileString (
|
||
|
Section,
|
||
|
NULL,
|
||
|
TEXT(""),
|
||
|
Keys,
|
||
|
Size,
|
||
|
IniFilePath
|
||
|
);
|
||
|
} while (chars == Size - 2);
|
||
|
|
||
|
return Keys;
|
||
|
}
|
||
|
|
||
|
|
||
|
PTSTR
|
||
|
pGetKeyValue (
|
||
|
IN PCTSTR IniFilePath,
|
||
|
IN PCTSTR Section,
|
||
|
IN PCTSTR Key
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
pGetKeyValue reads the value associated with the given key, section, INI file and returns
|
||
|
a pointer to allocated memory that contains this value as a string.
|
||
|
Both section and Key must not be NULL.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
IniFilePath - Specifies the INI file
|
||
|
|
||
|
Section - Specifies the section
|
||
|
|
||
|
Key - Specifies the key
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
A pointer to a string containing the value; caller must free the memory
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
PTSTR Value = NULL;
|
||
|
DWORD Size = 64 * sizeof (TCHAR);
|
||
|
DWORD chars;
|
||
|
|
||
|
MYASSERT (IniFilePath);
|
||
|
MYASSERT (Section);
|
||
|
MYASSERT (Key);
|
||
|
|
||
|
do {
|
||
|
if (Value) {
|
||
|
PoolMemReleaseMemory (g_IniActPool, Value);
|
||
|
}
|
||
|
Size *= 2;
|
||
|
Value = PoolMemGetMemory (g_IniActPool, Size);
|
||
|
chars = GetPrivateProfileString (
|
||
|
Section,
|
||
|
Key,
|
||
|
TEXT(""),
|
||
|
Value,
|
||
|
Size,
|
||
|
IniFilePath
|
||
|
);
|
||
|
} while (chars == Size - 1);
|
||
|
|
||
|
return Value;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
pIsFileActionRule (
|
||
|
IN PINIACT IniAct,
|
||
|
IN PINIFILE IniFile
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
pIsFileActionRule determines if the specified rule applies to the whole INI file
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
IniAct - Specifies the INI action
|
||
|
|
||
|
IniFile - Specifies the INI file
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
TRUE if the rule applies to the whole INI file, FALSE if not
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
MYASSERT (IniAct);
|
||
|
return !IniAct->RuleAttribs.Section && !IniAct->RuleAttribs.Key;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
pDoFileAction (
|
||
|
IN PINIACT IniAct,
|
||
|
IN PINIFILE IniFile
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
pDoFileAction applies the specified rule to the whole INI file
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
IniAct - Specifies the INI action
|
||
|
|
||
|
IniFile - Specifies the INI file
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
the result returned by the INI action processing function on this INI file
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
GROWBUFFER GbKeys = GROWBUF_INIT;
|
||
|
PTSTR Sections, Keys;
|
||
|
PCTSTR Section, Key;
|
||
|
BOOL Result;
|
||
|
|
||
|
MYASSERT (IniAct && IniAct->FnIniAct && !IniAct->RuleAttribs.Section && !IniAct->RuleAttribs.Key);
|
||
|
|
||
|
Sections = pGetAllKeys (IniFile->ActualLocation, NULL);
|
||
|
|
||
|
IniAct->RuleAttribs.Section = Sections;
|
||
|
|
||
|
for (Section = Sections; *Section; Section = pGetNextMultiSzString (Section)) {
|
||
|
Keys = pGetAllKeys (IniFile->ActualLocation, Section);
|
||
|
|
||
|
for (Key = Keys; *Key; Key = pGetNextMultiSzString (Key)) {
|
||
|
MultiSzAppend (&GbKeys, Key);
|
||
|
}
|
||
|
|
||
|
PoolMemReleaseMemory (g_IniActPool, Keys);
|
||
|
}
|
||
|
//
|
||
|
// end with another zero (here are 2 TCHAR zeroes...)
|
||
|
//
|
||
|
GrowBufAppendDword (&GbKeys, 0);
|
||
|
|
||
|
IniAct->RuleAttribs.Key = (PCTSTR)GbKeys.Buf;
|
||
|
|
||
|
Result = (*IniAct->FnIniAct)(&IniAct->RuleAttribs, IniFile);
|
||
|
|
||
|
IniAct->RuleAttribs.Key = NULL;
|
||
|
IniAct->RuleAttribs.Section = NULL;
|
||
|
|
||
|
FreeGrowBuffer (&GbKeys);
|
||
|
|
||
|
PoolMemReleaseMemory (g_IniActPool, Sections);
|
||
|
|
||
|
return Result;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
pIsSectionActionRule(
|
||
|
IN PINIACT IniAct,
|
||
|
IN PINIFILE IniFile
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
pIsSectionActionRule determines if the specified rule applies to a section
|
||
|
of the INI file
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
IniAct - Specifies the INI action
|
||
|
|
||
|
IniFile - Specifies the INI file
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
TRUE if the rule applies to a section of the INI file, FALSE if not
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
MYASSERT (IniAct);
|
||
|
return IniAct->RuleAttribs.Section && !IniAct->RuleAttribs.Key;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
pDoSectionAction (
|
||
|
IN PINIACT IniAct,
|
||
|
IN PINIFILE IniFile
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
pDoSectionAction applies the specified rule to a section of the INI file
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
IniAct - Specifies the INI action
|
||
|
|
||
|
IniFile - Specifies the INI file
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
the result returned by the INI action processing function
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
PTSTR Keys;
|
||
|
BOOL Result;
|
||
|
|
||
|
MYASSERT (IniAct && IniAct->FnIniAct && IniAct->RuleAttribs.Section && !IniAct->RuleAttribs.Key);
|
||
|
|
||
|
Keys = pGetAllKeys (IniFile->ActualLocation, IniAct->RuleAttribs.Section);
|
||
|
|
||
|
IniAct->RuleAttribs.Key = Keys;
|
||
|
|
||
|
Result = (*IniAct->FnIniAct)(&IniAct->RuleAttribs, IniFile);
|
||
|
|
||
|
IniAct->RuleAttribs.Key = NULL;
|
||
|
|
||
|
PoolMemReleaseMemory (g_IniActPool, Keys);
|
||
|
|
||
|
return Result;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
pDoKeyAction (
|
||
|
IN PINIACT IniAct,
|
||
|
IN PINIFILE IniFile
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
pDoKeyAction applies the specified rule to a key of the INI file
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
IniAct - Specifies the INI action
|
||
|
|
||
|
IniFile - Specifies the INI file
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
the result returned by the INI action processing function
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
MYASSERT (IniAct && IniAct->FnIniAct && IniAct->RuleAttribs.Key);
|
||
|
|
||
|
return (*IniAct->FnIniAct)(&IniAct->RuleAttribs, IniFile);
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
pDoIniAction (
|
||
|
IN PINIFILE IniFile
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This is the actual worker routine called by pDoIniActions for each INI file to
|
||
|
be migrated.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
IniFile - Specifies the INI file
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
TRUE if INI migration was successful for this file, FALSE otherwise
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
PINIACT IniAct;
|
||
|
BOOL Result = TRUE;
|
||
|
BOOL b;
|
||
|
|
||
|
//
|
||
|
// check INI file against all rules; if a rule applies, do it
|
||
|
//
|
||
|
if (pEnumFirstIniAction (&IniAct)) {
|
||
|
do {
|
||
|
if (!IsPatternMatch (IniAct->RuleAttribs.IniSpec, IniFile->OrigIniPath)) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// do the action; check for file actions first
|
||
|
//
|
||
|
if (pIsFileActionRule (IniAct, IniFile)) {
|
||
|
b = pDoFileAction (IniAct, IniFile);
|
||
|
} else {
|
||
|
//
|
||
|
// check section actions next
|
||
|
//
|
||
|
if (pIsSectionActionRule (IniAct, IniFile)) {
|
||
|
//
|
||
|
// do it for each section in the current file
|
||
|
//
|
||
|
b = pDoSectionAction (IniAct, IniFile);
|
||
|
} else {
|
||
|
//
|
||
|
// do key actions last
|
||
|
//
|
||
|
b = pDoKeyAction (IniAct, IniFile);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
DEBUGMSG_IF ((
|
||
|
!b,
|
||
|
DBG_INIACT,
|
||
|
"pDoIniActions: function [%s] failed on file [%s]",
|
||
|
IniAct->FnName,
|
||
|
IniFile->OrigIniPath
|
||
|
));
|
||
|
|
||
|
Result &= b;
|
||
|
|
||
|
} while (pEnumNextIniAction (&IniAct));
|
||
|
}
|
||
|
|
||
|
return Result;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
pDoIniActions (
|
||
|
IN INIACT_CONTEXT Context
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This is the actual worker routine called by DoIniActions. It may be called
|
||
|
in different contexts.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Context - Specifies the context in which the function is called
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
TRUE if INI files migration was successful, FALSE otherwise
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
MEMDB_ENUM e;
|
||
|
INIFILE IniFile;
|
||
|
PCTSTR OrigIniPath;
|
||
|
PCTSTR ActualLocation;
|
||
|
PCTSTR NtIniPath;
|
||
|
PCTSTR MemDbCategory;
|
||
|
|
||
|
//
|
||
|
// get all rules first
|
||
|
//
|
||
|
if (pCreateIniActions (Context)) {
|
||
|
//
|
||
|
// enum all candidates files from corresponding memdb category
|
||
|
//
|
||
|
if (Context == INIACT_WKS_FIRST) {
|
||
|
MemDbCategory = MEMDB_CATEGORY_INIACT_FIRST;
|
||
|
} else {
|
||
|
MemDbCategory = MEMDB_CATEGORY_INIACT_LAST;
|
||
|
}
|
||
|
if (MemDbGetValueEx (&e, MemDbCategory, NULL, NULL)) {
|
||
|
do {
|
||
|
OrigIniPath = e.szName;
|
||
|
|
||
|
ActualLocation = GetTemporaryLocationForFile (OrigIniPath);
|
||
|
if (!ActualLocation) {
|
||
|
DEBUGMSG ((
|
||
|
DBG_ERROR,
|
||
|
"Couldn't find temp location for INIACT key: %s\\%s",
|
||
|
MemDbCategory,
|
||
|
e.szName
|
||
|
));
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
NtIniPath = GetPathStringOnNt (OrigIniPath);
|
||
|
|
||
|
//
|
||
|
// fill in the members of IniFile
|
||
|
//
|
||
|
IniFile.OrigIniPath = OrigIniPath;
|
||
|
IniFile.ActualLocation = ActualLocation;
|
||
|
IniFile.NtIniPath = NtIniPath;
|
||
|
|
||
|
if (!pDoIniAction (&IniFile)) {
|
||
|
DEBUGMSG ((
|
||
|
DBG_INIACT,
|
||
|
"Some errors occured during migration of INI file [%s] -> [%s]",
|
||
|
OrigIniPath,
|
||
|
NtIniPath
|
||
|
));
|
||
|
}
|
||
|
//
|
||
|
// now convert the INI file (fix paths etc)
|
||
|
//
|
||
|
// ConvertIniFile (NtIniPath);
|
||
|
|
||
|
FreePathString (NtIniPath);
|
||
|
FreePathString (ActualLocation);
|
||
|
|
||
|
ZeroMemory (&IniFile, sizeof (IniFile));
|
||
|
|
||
|
} while (MemDbEnumNextValue (&e));
|
||
|
}
|
||
|
|
||
|
pFreeIniActions ();
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
DoIniActions (
|
||
|
IN INIACT_CONTEXT Context
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This is the main routine called to perform INI files migration. It may be called
|
||
|
several times, specifying the context.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Context - Specifies the context in which the function is called
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
TRUE if INI files migration was successful in that context, FALSE otherwise
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
BOOL b;
|
||
|
|
||
|
g_IniActPool = PoolMemInitNamedPool ("IniAct");
|
||
|
if (!g_IniActPool) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
b = FALSE;
|
||
|
__try {
|
||
|
b = pDoIniActions (Context);
|
||
|
}
|
||
|
__finally {
|
||
|
PoolMemDestroyPool (g_IniActPool);
|
||
|
g_IniActPool = NULL;
|
||
|
}
|
||
|
|
||
|
return b;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
pIsValidGuidStr (
|
||
|
IN PCTSTR GuidStr
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Determines if a GUID represented as a string has a valid representation (braces included).
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
GuidStr - Specifies the GUID to check; it must contain the surrounding braces
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
TRUE if the specified GUID is valid, or FALSE if it is not.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
DWORD GuidIdx, DashIdx;
|
||
|
BYTE DashIndexes[4] = { DASH_INDEXES };
|
||
|
TCHAR ch;
|
||
|
|
||
|
MYASSERT (GuidStr);
|
||
|
|
||
|
if (_tcslen (GuidStr) != GUIDSTR_LEN ||
|
||
|
GuidStr[0] != TEXT('{') ||
|
||
|
GuidStr[GUIDSTR_LEN - 1] != TEXT('}')) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
for (GuidIdx = 1, DashIdx = 0; GuidIdx < GUIDSTR_LEN - 1; GuidIdx++) {
|
||
|
//
|
||
|
// check all digits and dashes positions
|
||
|
//
|
||
|
ch = GuidStr[GuidIdx];
|
||
|
if (DashIdx < 4 && (BYTE)GuidIdx == DashIndexes[DashIdx]) {
|
||
|
if (ch != TEXT('-')) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
DashIdx++;
|
||
|
} else {
|
||
|
if (ch < TEXT('0') || ch > TEXT('9')) {
|
||
|
if (!(ch >= TEXT('A') && ch <= TEXT('F') || ch >= TEXT('a') && ch <= TEXT('f'))) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
pIsGuidSuppressed (
|
||
|
PCTSTR GuidStr
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Determines if a GUID is suppressed or not.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
GuidStr - Specifies the GUID to look up, which must be valid and
|
||
|
must contain the surrounding braces
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
TRUE if the specified GUID is suppressed, or FALSE if it is not.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
TCHAR Node[MEMDB_MAX];
|
||
|
|
||
|
MemDbBuildKey (
|
||
|
Node,
|
||
|
MEMDB_CATEGORY_GUIDS,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
GuidStr
|
||
|
);
|
||
|
|
||
|
return MemDbGetValue (Node, NULL);
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
pIsValidShellExtClsid (
|
||
|
IN PCTSTR GuidStr
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
pIsValidShellExtClsid determines if a GUID is a valid shell extension
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
GuidStr - Specifies the GUID to look up, which must be valid and
|
||
|
must contain the surrounding braces
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
TRUE if the specified GUID is a valid shell ext, or FALSE if it is not.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
#if 0
|
||
|
HKEY Key;
|
||
|
LONG rc;
|
||
|
#endif
|
||
|
|
||
|
//
|
||
|
// check if the GUID is a known bad guid
|
||
|
//
|
||
|
if (pIsGuidSuppressed (GuidStr)) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
return TRUE;
|
||
|
|
||
|
//
|
||
|
// I removed the registry check because it is not always accurate;
|
||
|
// some GUIDS may work without being listed in S_SHELLEXT_APPROVED keys
|
||
|
// as it's the case with the default GUID {5984FFE0-28D4-11CF-AE66-08002B2E1262}
|
||
|
//
|
||
|
#if 0
|
||
|
rc = TrackedRegOpenKeyEx (
|
||
|
HKEY_LOCAL_MACHINE,
|
||
|
S_SHELLEXT_APPROVED,
|
||
|
0,
|
||
|
KEY_QUERY_VALUE,
|
||
|
&Key
|
||
|
);
|
||
|
if (rc == ERROR_SUCCESS) {
|
||
|
rc = RegQueryValueEx (Key, GuidStr, NULL, NULL, NULL, NULL);
|
||
|
CloseRegKey (Key);
|
||
|
}
|
||
|
|
||
|
if (rc == ERROR_SUCCESS) {
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
return FALSE;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
pFindStrInMultiSzStrI (
|
||
|
IN PCTSTR Str,
|
||
|
IN PCTSTR MultiSz
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
pFindStrInMultiSzStrI looks for Str in a list of multi-sz; the search is case-insensitive
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Str - Specifies the string to look for
|
||
|
|
||
|
MultiSz - Specifies the list to be searched
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
TRUE if the string was found in the list, or FALSE if not.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
PCTSTR p;
|
||
|
|
||
|
for (p = MultiSz; *p; p = pGetNextMultiSzString (p)) {
|
||
|
if (StringIMatch (p, Str)) {
|
||
|
return TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
pMigrateSection (
|
||
|
IN PCTSTR Section,
|
||
|
IN PRULEATTRIBS RuleAttribs,
|
||
|
IN PINIFILE IniFile
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
pMigrateSection migrates a whole section of the INI file.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Section - Specifies section name
|
||
|
|
||
|
RuleAttribs - Specifies the rule attributes which govern the migration
|
||
|
|
||
|
IniFile - Specifies the INI file
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
TRUE if the section was transferred successfully, or FALSE if not.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
PTSTR Keys;
|
||
|
PTSTR Value;
|
||
|
PCTSTR Key;
|
||
|
BOOL b = TRUE;
|
||
|
|
||
|
Keys = pGetAllKeys (IniFile->ActualLocation, Section);
|
||
|
|
||
|
if (*Keys) {
|
||
|
//
|
||
|
// there are keys to transfer; first remove the entire section that will be replaced
|
||
|
//
|
||
|
WritePrivateProfileString (
|
||
|
Section,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
IniFile->NtIniPath
|
||
|
);
|
||
|
}
|
||
|
|
||
|
for (Key = Keys; *Key; Key = pGetNextMultiSzString (Key)) {
|
||
|
Value = pGetKeyValue (IniFile->ActualLocation, Section, Key);
|
||
|
b &= WritePrivateProfileString (
|
||
|
Section,
|
||
|
Key,
|
||
|
Value,
|
||
|
IniFile->NtIniPath
|
||
|
);
|
||
|
|
||
|
PoolMemReleaseMemory (g_IniActPool, Value);
|
||
|
}
|
||
|
|
||
|
PoolMemReleaseMemory (g_IniActPool, Keys);
|
||
|
|
||
|
return b;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
MigrateDesktopIniSCI (
|
||
|
IN PRULEATTRIBS RuleAttribs,
|
||
|
IN PINIFILE IniFile
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
MigrateDesktopIniSCI migrates desktop.ini settings in section [.ShellClassInfo].
|
||
|
It reads all keys and associated values within the section and writes them back
|
||
|
to the NT version of this file. The "settings" multisz in this case represents
|
||
|
a list of keys that must be synchronized; if no Win9x key exists, the corresponding
|
||
|
NT key must be deleted; if the Win9x key exists, its value is copied
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
RuleAttribs - Specifies the rule attributes which govern the migration
|
||
|
|
||
|
IniFile - Specifies the INI file
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
TRUE if the section was transferred successfully, or FALSE if an error occured.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
PCTSTR Key, SKey, NewValue;
|
||
|
BOOL Found;
|
||
|
BOOL Result, b;
|
||
|
PTSTR Win9xValue, NtValue;
|
||
|
TCHAR Dummy[2];
|
||
|
|
||
|
DEBUGMSG ((
|
||
|
DBG_INIACT,
|
||
|
"Processing: %s -> %s [%s]",
|
||
|
IniFile->OrigIniPath,
|
||
|
IniFile->NtIniPath,
|
||
|
RuleAttribs->Section
|
||
|
));
|
||
|
|
||
|
Result = TRUE;
|
||
|
//
|
||
|
// RuleAttribs->Settings points in this case to a list of keys that
|
||
|
// must be synchronized; if no Win9x key exists, the corresponding
|
||
|
// NT key must be deleted; if Win9x key exists, its value is copied
|
||
|
//
|
||
|
for (SKey = (PCTSTR)RuleAttribs->Settings.Buf;
|
||
|
*SKey;
|
||
|
SKey = pGetNextMultiSzString (SKey)
|
||
|
) {
|
||
|
|
||
|
Found = FALSE;
|
||
|
for (Key = RuleAttribs->Key; *Key; Key = pGetNextMultiSzString (Key)) {
|
||
|
if (StringIMatch (SKey, Key)) {
|
||
|
Found = TRUE;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if (!Found) {
|
||
|
//
|
||
|
// remove NT key if there is one
|
||
|
//
|
||
|
if (GetPrivateProfileString (
|
||
|
RuleAttribs->Section,
|
||
|
SKey,
|
||
|
TEXT(""),
|
||
|
Dummy,
|
||
|
2,
|
||
|
IniFile->NtIniPath
|
||
|
)) {
|
||
|
if (!WritePrivateProfileString (
|
||
|
RuleAttribs->Section,
|
||
|
SKey,
|
||
|
NULL,
|
||
|
IniFile->NtIniPath
|
||
|
)) {
|
||
|
Result = FALSE;
|
||
|
DEBUGMSG ((DBG_INIACT, "Couldn't remove NT key [%s]", SKey));
|
||
|
}
|
||
|
ELSE_DEBUGMSG ((DBG_INIACT, "Removed NT key [%s]", SKey));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for (Key = RuleAttribs->Key; *Key; Key = pGetNextMultiSzString (Key)) {
|
||
|
//
|
||
|
// for each key on Win9x, update NT value;
|
||
|
// check for suppressed GUIDs
|
||
|
//
|
||
|
Win9xValue = pGetKeyValue (IniFile->ActualLocation, RuleAttribs->Section, Key);
|
||
|
NewValue = Win9xValue;
|
||
|
if (pIsValidGuidStr (NewValue) && pIsGuidSuppressed (NewValue)) {
|
||
|
//
|
||
|
// remove the key
|
||
|
//
|
||
|
NewValue = NULL;
|
||
|
}
|
||
|
|
||
|
NtValue = pGetKeyValue (IniFile->NtIniPath, RuleAttribs->Section, Key);
|
||
|
if (!NewValue && *NtValue || !StringMatch (NewValue, NtValue)) {
|
||
|
b = WritePrivateProfileString (
|
||
|
RuleAttribs->Section,
|
||
|
Key,
|
||
|
NewValue,
|
||
|
IniFile->NtIniPath
|
||
|
);
|
||
|
if (b) {
|
||
|
DEBUGMSG ((
|
||
|
DBG_INIACT,
|
||
|
"Replaced key [%s] NT value [%s] with 9x value [%s]",
|
||
|
Key,
|
||
|
NtValue,
|
||
|
Win9xValue));
|
||
|
} else {
|
||
|
Result = FALSE;
|
||
|
DEBUGMSG ((
|
||
|
DBG_INIACT,
|
||
|
"Failed to replace key [%s] NT value [%s] with 9x value [%s]",
|
||
|
Key,
|
||
|
NtValue,
|
||
|
Win9xValue));
|
||
|
}
|
||
|
}
|
||
|
PoolMemReleaseMemory (g_IniActPool, Win9xValue);
|
||
|
PoolMemReleaseMemory (g_IniActPool, NtValue);
|
||
|
}
|
||
|
|
||
|
return Result;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
MigrateDesktopIniESFV (
|
||
|
IN PRULEATTRIBS RuleAttribs,
|
||
|
IN PINIFILE IniFile
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
MigrateDesktopIniESFV migrates desktop.ini settings in section [ExtShellFolderViews].
|
||
|
It reads all keys and associated values within the section and writes them back
|
||
|
to the NT version of this file. The "settings" multisz is not interpreted in this case.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
RuleAttribs - Specifies the rule attributes which govern the migration
|
||
|
|
||
|
IniFile - Specifies the INI file
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
TRUE if the section was transferred successfully, or FALSE if an error occured.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
PCTSTR ViewID;
|
||
|
BOOL b, Result;
|
||
|
DWORD chars;
|
||
|
PTSTR Win9xValue;
|
||
|
TCHAR DefaultViewID[GUIDSTR_LEN + 2];
|
||
|
BOOL ReplaceDefViewID = FALSE;
|
||
|
PTSTR NtValue;
|
||
|
#ifdef DEBUG
|
||
|
TCHAR NtViewID[GUIDSTR_LEN + 2];
|
||
|
#endif
|
||
|
|
||
|
Result = TRUE;
|
||
|
|
||
|
DEBUGMSG ((
|
||
|
DBG_INIACT,
|
||
|
"Processing: %s -> %s [%s]",
|
||
|
IniFile->OrigIniPath,
|
||
|
IniFile->NtIniPath,
|
||
|
RuleAttribs->Section
|
||
|
));
|
||
|
|
||
|
//
|
||
|
// get the default view id
|
||
|
//
|
||
|
chars = GetPrivateProfileString (
|
||
|
RuleAttribs->Section,
|
||
|
S_DEFAULT,
|
||
|
TEXT(""),
|
||
|
DefaultViewID,
|
||
|
GUIDSTR_LEN + 2,
|
||
|
IniFile->ActualLocation
|
||
|
);
|
||
|
if (*DefaultViewID && chars != GUIDSTR_LEN || !pIsValidShellExtClsid (DefaultViewID)) {
|
||
|
//
|
||
|
// invalid view id
|
||
|
//
|
||
|
DEBUGMSG ((
|
||
|
DBG_INIACT,
|
||
|
"Invalid Default ViewID [%s]; will not be processed",
|
||
|
DefaultViewID
|
||
|
));
|
||
|
*DefaultViewID = 0;
|
||
|
}
|
||
|
|
||
|
for (ViewID = RuleAttribs->Key; *ViewID; ViewID = pGetNextMultiSzString (ViewID)) {
|
||
|
//
|
||
|
// except for Default={ViewID},
|
||
|
// all the other lines in this section should have the format {ViewID}=value
|
||
|
// for each {ViewID} there is a section with the same name
|
||
|
// keeping other keys (attributes of that shell view)
|
||
|
//
|
||
|
if (StringIMatch (ViewID, S_DEFAULT)) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (pIsValidGuidStr (ViewID) && pIsValidShellExtClsid (ViewID)) {
|
||
|
//
|
||
|
// transfer the whole GUID section, if it's not one that shouldn't be migrated
|
||
|
// a list of GUIDS that shouldn't be migrated is in RuleAttribs->Settings
|
||
|
//
|
||
|
if (!pFindStrInMultiSzStrI (ViewID, (PCTSTR)RuleAttribs->Settings.Buf)) {
|
||
|
|
||
|
b = pMigrateSection (ViewID, RuleAttribs, IniFile);
|
||
|
|
||
|
if (b) {
|
||
|
DEBUGMSG ((DBG_INIACT, "Successfully migrated section [%s]", ViewID));
|
||
|
if (*DefaultViewID && !StringIMatch (ViewID, DefaultViewID)) {
|
||
|
ReplaceDefViewID = TRUE;
|
||
|
}
|
||
|
//
|
||
|
// set {ViewID}=value in NT desktop.ini
|
||
|
//
|
||
|
NtValue = pGetKeyValue (IniFile->NtIniPath, RuleAttribs->Section, ViewID);
|
||
|
Win9xValue = pGetKeyValue (
|
||
|
IniFile->ActualLocation,
|
||
|
RuleAttribs->Section,
|
||
|
ViewID
|
||
|
);
|
||
|
if (!StringIMatch (NtValue, Win9xValue)) {
|
||
|
b = WritePrivateProfileString (
|
||
|
RuleAttribs->Section,
|
||
|
ViewID,
|
||
|
Win9xValue,
|
||
|
IniFile->NtIniPath
|
||
|
);
|
||
|
DEBUGMSG_IF ((
|
||
|
b,
|
||
|
DBG_INIACT,
|
||
|
"Replaced key [%s] NT value [%s] with 9x value [%s]",
|
||
|
ViewID,
|
||
|
NtValue,
|
||
|
Win9xValue));
|
||
|
} else {
|
||
|
b = TRUE;
|
||
|
}
|
||
|
|
||
|
PoolMemReleaseMemory (g_IniActPool, Win9xValue);
|
||
|
PoolMemReleaseMemory (g_IniActPool, NtValue);
|
||
|
}
|
||
|
ELSE_DEBUGMSG ((DBG_INIACT, "Section [%s] was not migrated successfully", ViewID));
|
||
|
//
|
||
|
// update global result
|
||
|
//
|
||
|
Result &= b;
|
||
|
}
|
||
|
}
|
||
|
ELSE_DEBUGMSG ((DBG_INIACT, "Invalid ShellExtViewID: [%s]; will not be processed", ViewID));
|
||
|
|
||
|
}
|
||
|
|
||
|
if (ReplaceDefViewID) {
|
||
|
//
|
||
|
// replace NT default view with Win9x default view
|
||
|
//
|
||
|
#ifdef DEBUG
|
||
|
GetPrivateProfileString (
|
||
|
RuleAttribs->Section,
|
||
|
S_DEFAULT,
|
||
|
TEXT(""),
|
||
|
NtViewID,
|
||
|
GUIDSTR_LEN + 2,
|
||
|
IniFile->NtIniPath
|
||
|
);
|
||
|
#endif
|
||
|
b = WritePrivateProfileString (
|
||
|
RuleAttribs->Section,
|
||
|
S_DEFAULT,
|
||
|
DefaultViewID,
|
||
|
IniFile->NtIniPath
|
||
|
);
|
||
|
DEBUGMSG_IF ((
|
||
|
b,
|
||
|
DBG_INIACT,
|
||
|
"Replaced default NT ViewID [%s] with Default Win9x ViewID [%s]",
|
||
|
NtViewID,
|
||
|
DefaultViewID));
|
||
|
|
||
|
Result &= b;
|
||
|
}
|
||
|
|
||
|
return Result;
|
||
|
}
|