You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2829 lines
90 KiB
2829 lines
90 KiB
/*++
|
|
|
|
Copyright (c) 2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
opm.c
|
|
|
|
Abstract:
|
|
|
|
Implements the data apply portion of scanstate v1 compatiblity.
|
|
|
|
Author:
|
|
|
|
Jim Schmidt (jimschm) 12-Mar-2000
|
|
|
|
Revision History:
|
|
|
|
<alias> <date> <comments>
|
|
|
|
--*/
|
|
|
|
//
|
|
// Includes
|
|
//
|
|
|
|
#include "pch.h"
|
|
#include "v1p.h"
|
|
#include <sddl.h>
|
|
|
|
#define DBG_V1 "v1"
|
|
#define MAXINISIZE 65536
|
|
|
|
//
|
|
// Strings
|
|
//
|
|
|
|
#define S_RENAMEEX_START_CHAR TEXT('<')
|
|
#define S_RENAMEEX_END_CHAR TEXT('>')
|
|
|
|
//
|
|
// Constants
|
|
//
|
|
|
|
// None
|
|
|
|
//
|
|
// Macros
|
|
//
|
|
|
|
// None
|
|
|
|
//
|
|
// Types
|
|
//
|
|
|
|
// None
|
|
|
|
//
|
|
// Globals
|
|
//
|
|
|
|
MIG_OPERATIONID g_V1MoveExOp;
|
|
MIG_OPERATIONID g_V1MoveOp;
|
|
MIG_OPERATIONID g_DeleteOp;
|
|
MIG_OPERATIONID g_PartMoveOp;
|
|
PMAPSTRUCT g_RegNodeFilterMap;
|
|
PMAPSTRUCT g_RegLeafFilterMap;
|
|
PMAPSTRUCT g_FileNodeFilterMap;
|
|
PMAPSTRUCT g_FileLeafFilterMap;
|
|
PMAPSTRUCT g_IniSectFilterMap;
|
|
PMAPSTRUCT g_IniKeyFilterMap;
|
|
PMAPSTRUCT g_DestEnvMap;
|
|
HASHTABLE g_RegCollisionDestTable;
|
|
HASHTABLE g_RegCollisionSrcTable;
|
|
|
|
//
|
|
// Macro expansion list
|
|
//
|
|
|
|
// None
|
|
|
|
//
|
|
// Private function prototypes
|
|
//
|
|
|
|
OPMINITIALIZE ScriptOpmInitialize;
|
|
OPMFILTERCALLBACK FilterV1MoveEx;
|
|
OPMFILTERCALLBACK FilterV1Move;
|
|
OPMFILTERCALLBACK FilterMove;
|
|
OPMFILTERCALLBACK FilterIniMove;
|
|
OPMAPPLYCALLBACK DoRegAutoFilter;
|
|
OPMAPPLYCALLBACK DoIniAutoFilter;
|
|
OPMFILTERCALLBACK FilterRegAutoFilter;
|
|
OPMFILTERCALLBACK FilterIniAutoFilter;
|
|
OPMFILTERCALLBACK FilterFileAutoFilter;
|
|
OPMFILTERCALLBACK FilterDelete;
|
|
OPMAPPLYCALLBACK DoFixDefaultIcon;
|
|
OPMFILTERCALLBACK FilterRenameExFilter;
|
|
OPMFILTERCALLBACK FilterRenameIniExFilter;
|
|
OPMFILTERCALLBACK FilterPartitionMove;
|
|
OPMAPPLYCALLBACK DoDestAddObject;
|
|
|
|
//
|
|
// Macro expansion definition
|
|
//
|
|
|
|
// None
|
|
|
|
//
|
|
// Code
|
|
//
|
|
|
|
BOOL
|
|
pParseInfForRemapEnvVar (
|
|
IN HINF InfHandle
|
|
)
|
|
{
|
|
INFSTRUCT is = INITINFSTRUCT_PMHANDLE;
|
|
PCTSTR envVar;
|
|
PTSTR envValue;
|
|
UINT sizeNeeded;
|
|
PTSTR encodedVariableName;
|
|
BOOL result = FALSE;
|
|
|
|
__try {
|
|
|
|
// on all systems, process "Delete Destination Settings"
|
|
if (InfFindFirstLine (InfHandle, TEXT("RemapEnvVar"), NULL, &is)) {
|
|
do {
|
|
|
|
if (IsmCheckCancel()) {
|
|
__leave;
|
|
}
|
|
|
|
envVar = InfGetStringField (&is, 1);
|
|
|
|
if (!envVar) {
|
|
LOG ((LOG_WARNING, (PCSTR) MSG_EMPTY_REG_SPEC));
|
|
continue;
|
|
}
|
|
|
|
if (IsmGetEnvironmentString (
|
|
PLATFORM_DESTINATION,
|
|
S_SYSENVVAR_GROUP,
|
|
envVar,
|
|
NULL,
|
|
0,
|
|
&sizeNeeded
|
|
)) {
|
|
|
|
envValue = AllocPathString (sizeNeeded);
|
|
if (envValue) {
|
|
|
|
if (IsmGetEnvironmentString (
|
|
PLATFORM_DESTINATION,
|
|
S_SYSENVVAR_GROUP,
|
|
envVar,
|
|
envValue,
|
|
sizeNeeded,
|
|
NULL
|
|
)) {
|
|
AddRemappingEnvVar (g_DestEnvMap, g_FileNodeFilterMap, NULL, envVar, envValue);
|
|
}
|
|
FreePathString (envValue);
|
|
envValue = NULL;
|
|
}
|
|
}
|
|
|
|
// now let's see if this env. variable was present on the source machine.
|
|
// If it was, we are going to add it into g_RevEnvMap to allow file move
|
|
// to create subdirectories only from this variable up.
|
|
if (IsmGetEnvironmentString (
|
|
PLATFORM_SOURCE,
|
|
S_SYSENVVAR_GROUP,
|
|
envVar,
|
|
NULL,
|
|
0,
|
|
&sizeNeeded
|
|
)) {
|
|
|
|
envValue = AllocPathString (sizeNeeded);
|
|
if (envValue) {
|
|
if (IsmGetEnvironmentString (
|
|
PLATFORM_SOURCE,
|
|
S_SYSENVVAR_GROUP,
|
|
envVar,
|
|
envValue,
|
|
sizeNeeded,
|
|
NULL
|
|
)) {
|
|
encodedVariableName = AllocPathString (TcharCount (envVar) + 3);
|
|
if (encodedVariableName) {
|
|
wsprintf (encodedVariableName, TEXT("%%%s%%"), envVar);
|
|
AddStringMappingPair (g_RevEnvMap, envValue, encodedVariableName);
|
|
FreePathString (encodedVariableName);
|
|
encodedVariableName = NULL;
|
|
}
|
|
|
|
}
|
|
FreePathString (envValue);
|
|
envValue = NULL;
|
|
}
|
|
}
|
|
|
|
} while (InfFindNextLine (&is));
|
|
}
|
|
|
|
result = TRUE;
|
|
}
|
|
__finally {
|
|
InfCleanUpInfStruct (&is);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
BOOL
|
|
pParseRemapEnvVar (
|
|
VOID
|
|
)
|
|
{
|
|
PTSTR multiSz = NULL;
|
|
MULTISZ_ENUM e;
|
|
UINT sizeNeeded;
|
|
HINF infHandle = INVALID_HANDLE_VALUE;
|
|
ENVENTRY_TYPE dataType;
|
|
BOOL result = TRUE;
|
|
|
|
if (IsmGetEnvironmentValue (
|
|
IsmGetRealPlatform (),
|
|
NULL,
|
|
S_GLOBAL_INF_HANDLE,
|
|
(PBYTE)(&infHandle),
|
|
sizeof (HINF),
|
|
&sizeNeeded,
|
|
&dataType
|
|
) &&
|
|
(sizeNeeded == sizeof (HINF)) &&
|
|
(dataType == ENVENTRY_BINARY)
|
|
) {
|
|
if (!pParseInfForRemapEnvVar (infHandle)) {
|
|
result = FALSE;
|
|
}
|
|
} else {
|
|
|
|
if (!IsmGetEnvironmentValue (IsmGetRealPlatform (), NULL, S_INF_FILE_MULTISZ, NULL, 0, &sizeNeeded, NULL)) {
|
|
return TRUE; // no INF files specified
|
|
}
|
|
|
|
__try {
|
|
multiSz = AllocText (sizeNeeded);
|
|
if (!multiSz) {
|
|
result = FALSE;
|
|
__leave;
|
|
}
|
|
|
|
if (!IsmGetEnvironmentValue (IsmGetRealPlatform (), NULL, S_INF_FILE_MULTISZ, (PBYTE) multiSz, sizeNeeded, NULL, NULL)) {
|
|
result = FALSE;
|
|
__leave;
|
|
}
|
|
|
|
if (EnumFirstMultiSz (&e, multiSz)) {
|
|
|
|
do {
|
|
infHandle = InfOpenInfFile (e.CurrentString);
|
|
if (infHandle != INVALID_HANDLE_VALUE) {
|
|
if (!pParseInfForRemapEnvVar (infHandle)) {
|
|
InfCloseInfFile (infHandle);
|
|
infHandle = INVALID_HANDLE_VALUE;
|
|
result = FALSE;
|
|
__leave;
|
|
}
|
|
|
|
InfCloseInfFile (infHandle);
|
|
infHandle = INVALID_HANDLE_VALUE;
|
|
} else {
|
|
LOG ((LOG_ERROR, (PCSTR) MSG_CANT_OPEN_INF, e.CurrentString));
|
|
}
|
|
} while (EnumNextMultiSz (&e));
|
|
|
|
}
|
|
}
|
|
__finally {
|
|
if (multiSz) {
|
|
FreeText (multiSz);
|
|
multiSz = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
VOID
|
|
pOutlookClearConvKeys (
|
|
VOID
|
|
)
|
|
{
|
|
MIG_CONTENT objectContent;
|
|
MIG_OBJECT_ENUM objectEnum;
|
|
MIG_OBJECTSTRINGHANDLE enumPattern = NULL;
|
|
|
|
// This registry tree was needed only for conversion data. We don't want to
|
|
// write them to the destination, so clear the apply attribute on each item.
|
|
|
|
if ((IsmIsComponentSelected (S_OUTLOOK9798_COMPONENT, 0) &&
|
|
IsmIsEnvironmentFlagSet (PLATFORM_SOURCE, NULL, S_OUTLOOK9798_APPDETECT)) ||
|
|
(IsmIsComponentSelected (S_OFFICE_COMPONENT, 0) &&
|
|
IsmIsEnvironmentFlagSet (PLATFORM_SOURCE, NULL, S_OFFICE9798_APPDETECT))) {
|
|
|
|
enumPattern = IsmCreateSimpleObjectPattern (
|
|
TEXT("HKLM\\Software\\Microsoft\\MS Setup (ACME)\\Table Files"),
|
|
TRUE,
|
|
NULL,
|
|
TRUE);
|
|
|
|
if (IsmEnumFirstSourceObject (&objectEnum, g_RegType, enumPattern)) {
|
|
do {
|
|
IsmClearApplyOnObject (g_RegType | PLATFORM_SOURCE, objectEnum.ObjectName);
|
|
} while (IsmEnumNextObject (&objectEnum));
|
|
}
|
|
IsmDestroyObjectHandle (enumPattern);
|
|
}
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
ScriptOpmInitialize (
|
|
IN PMIG_LOGCALLBACK LogCallback,
|
|
IN PVOID Reserved
|
|
)
|
|
{
|
|
//
|
|
// Get file and registry types
|
|
//
|
|
g_FileType = MIG_FILE_TYPE;
|
|
g_RegType = MIG_REGISTRY_TYPE;
|
|
g_IniType = MIG_INI_TYPE;
|
|
|
|
//
|
|
// Get attribute and operation types
|
|
//
|
|
g_V1MoveExOp = IsmRegisterOperation (S_OPERATION_V1_FILEMOVEEX, TRUE);
|
|
g_V1MoveOp = IsmRegisterOperation (S_OPERATION_V1_FILEMOVE, TRUE);
|
|
g_RenameOp = IsmRegisterOperation (S_OPERATION_MOVE, FALSE);
|
|
g_RenameIniOp = IsmRegisterOperation (S_OPERATION_INIMOVE, FALSE);
|
|
g_DeleteOp = IsmRegisterOperation (S_OPERATION_DELETE, FALSE);
|
|
g_DefaultIconOp = IsmRegisterOperation (S_OPERATION_DEFICON_FIXCONTENT, FALSE);
|
|
g_DefaultIconData = IsmRegisterProperty (S_V1PROP_ICONDATA, FALSE);
|
|
g_FileCollPatternData = IsmRegisterProperty (S_V1PROP_FILECOLLPATTERN, FALSE);
|
|
g_RenameExOp = IsmRegisterOperation (S_OPERATION_ENHANCED_MOVE, FALSE);
|
|
g_RenameIniExOp = IsmRegisterOperation (S_OPERATION_ENHANCED_INIMOVE, FALSE);
|
|
g_PartMoveOp = IsmRegisterOperation (S_OPERATION_PARTITION_MOVE, TRUE);
|
|
g_DestAddObject = IsmRegisterOperation (S_OPERATION_DESTADDOBJ, FALSE);
|
|
g_RegAutoFilterOp = IsmRegisterOperation (S_OPERATION_REG_AUTO_FILTER, FALSE);
|
|
g_IniAutoFilterOp = IsmRegisterOperation (S_OPERATION_INI_AUTO_FILTER, FALSE);
|
|
|
|
//
|
|
// Register operation callbacks
|
|
//
|
|
|
|
// FYI: Filter callbacks adjust the name of the object
|
|
// Apply callbacks adjust the content of the object
|
|
|
|
// global operation callbacks
|
|
IsmRegisterGlobalApplyCallback (g_RegType | PLATFORM_SOURCE, TEXT("ContentAutoFilter"), DoRegAutoFilter);
|
|
IsmRegisterGlobalApplyCallback (g_IniType | PLATFORM_SOURCE, TEXT("ContentAutoFilter"), DoIniAutoFilter);
|
|
IsmRegisterGlobalFilterCallback (g_RegType | PLATFORM_SOURCE, TEXT("AutoFilter"), FilterRegAutoFilter, TRUE, FALSE);
|
|
IsmRegisterGlobalFilterCallback (g_IniType | PLATFORM_SOURCE, TEXT("AutoFilter"), FilterIniAutoFilter, TRUE, FALSE);
|
|
IsmRegisterGlobalFilterCallback (g_FileType | PLATFORM_SOURCE, TEXT("AutoFilter"), FilterFileAutoFilter, TRUE, TRUE);
|
|
|
|
// operation-specific callbacks
|
|
IsmRegisterOperationFilterCallback (g_V1MoveExOp, FilterV1MoveEx, TRUE, TRUE, FALSE);
|
|
IsmRegisterOperationFilterCallback (g_V1MoveOp, FilterV1Move, TRUE, TRUE, FALSE);
|
|
IsmRegisterOperationFilterCallback (g_RenameOp, FilterMove, TRUE, TRUE, FALSE);
|
|
IsmRegisterOperationFilterCallback (g_RenameIniOp, FilterIniMove, TRUE, TRUE, FALSE);
|
|
IsmRegisterOperationFilterCallback (g_DeleteOp, FilterDelete, FALSE, TRUE, FALSE);
|
|
IsmRegisterOperationApplyCallback (g_DefaultIconOp, DoFixDefaultIcon, TRUE);
|
|
IsmRegisterOperationFilterCallback (g_RenameExOp, FilterRenameExFilter, TRUE, TRUE, FALSE);
|
|
IsmRegisterOperationFilterCallback (g_RenameIniExOp, FilterRenameIniExFilter, TRUE, TRUE, FALSE);
|
|
IsmRegisterOperationFilterCallback (g_PartMoveOp, FilterPartitionMove, TRUE, TRUE, FALSE);
|
|
IsmRegisterOperationApplyCallback (g_DestAddObject, DoDestAddObject, TRUE);
|
|
IsmRegisterOperationApplyCallback (g_RegAutoFilterOp, DoRegAutoFilter, TRUE);
|
|
IsmRegisterOperationApplyCallback (g_IniAutoFilterOp, DoIniAutoFilter, TRUE);
|
|
|
|
//
|
|
// Call special conversion entry point
|
|
//
|
|
InitSpecialConversion (PLATFORM_DESTINATION);
|
|
InitSpecialRename (PLATFORM_DESTINATION);
|
|
|
|
g_RegNodeFilterMap = CreateStringMapping();
|
|
|
|
g_FileNodeFilterMap = CreateStringMapping();
|
|
|
|
g_DestEnvMap = CreateStringMapping();
|
|
|
|
SetIsmEnvironmentFromPhysicalMachine (g_DestEnvMap, FALSE, NULL);
|
|
SetIsmEnvironmentFromPhysicalMachine (g_FileNodeFilterMap, TRUE, NULL);
|
|
|
|
pParseRemapEnvVar ();
|
|
|
|
g_RegLeafFilterMap = CreateStringMapping();
|
|
|
|
g_FileLeafFilterMap = CreateStringMapping();
|
|
|
|
if ((!g_EnvMap) || (!g_RevEnvMap) || (!g_UndefMap)) {
|
|
g_EnvMap = CreateStringMapping();
|
|
g_UndefMap = CreateStringMapping();
|
|
g_RevEnvMap = CreateStringMapping();
|
|
SetIsmEnvironmentFromVirtualMachine (g_EnvMap, g_RevEnvMap, g_UndefMap);
|
|
}
|
|
|
|
g_IniSectFilterMap = CreateStringMapping ();
|
|
g_IniKeyFilterMap = CreateStringMapping ();
|
|
|
|
g_RegCollisionDestTable = HtAllocWithData (sizeof (MIG_OBJECTSTRINGHANDLE));
|
|
g_RegCollisionSrcTable = HtAllocWithData (sizeof (HASHITEM));
|
|
|
|
InitRestoreCallback (PLATFORM_DESTINATION);
|
|
|
|
pOutlookClearConvKeys();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
pDoesDifferentRegExist (
|
|
IN MIG_OBJECTSTRINGHANDLE DestName
|
|
)
|
|
{
|
|
BOOL result = FALSE;
|
|
MIG_CONTENT content;
|
|
|
|
if (IsmAcquireObject (g_RegType|PLATFORM_DESTINATION, DestName, &content)) {
|
|
IsmReleaseObject (&content);
|
|
result = TRUE;
|
|
} else if (HtFindString (g_RegCollisionDestTable, DestName)) {
|
|
result = TRUE;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
FilterV1MoveEx (
|
|
IN PCMIG_FILTERINPUT InputData,
|
|
OUT PMIG_FILTEROUTPUT OutputData,
|
|
IN BOOL NoRestoreObject,
|
|
IN PCMIG_BLOB SourceOperationData, OPTIONAL
|
|
IN PCMIG_BLOB DestinationOperationData OPTIONAL
|
|
)
|
|
{
|
|
PCTSTR orgSrcNode = NULL;
|
|
PCTSTR orgSrcLeaf = NULL;
|
|
PCTSTR srcNode = NULL;
|
|
PCTSTR srcLeaf = NULL;
|
|
PCTSTR destNode = NULL;
|
|
PCTSTR destLeaf = NULL;
|
|
PCTSTR newDestNode = NULL;
|
|
PCTSTR destNodePtr = NULL;
|
|
// NTRAID#NTBUG9-153274-2000/08/01-jimschm Static buffer size
|
|
TCHAR expDestNode[MAX_PATH * 4];
|
|
PCTSTR ismExpDestNode = NULL;
|
|
TCHAR expDestLeaf[MAX_PATH * 4];
|
|
PCTSTR ismExpDestLeaf = NULL;
|
|
CHARTYPE ch;
|
|
MIG_OBJECTSTRINGHANDLE destHandle;
|
|
|
|
__try {
|
|
|
|
//
|
|
// For v1 compatibility, we support only a transformation from
|
|
// original source to inf-specified destination. Chaining of
|
|
// operations is not allowed (these are restrictions caused by the
|
|
// existing INF syntax).
|
|
//
|
|
|
|
if (!DestinationOperationData) {
|
|
DEBUGMSG ((DBG_ERROR, "Missing dest data in FilterV1MoveEx"));
|
|
__leave;
|
|
}
|
|
|
|
if ((InputData->CurrentObject.ObjectTypeId & (~PLATFORM_MASK)) != g_FileType) {
|
|
DEBUGMSG ((DBG_ERROR, "Unexpected object type in FilterV1MoveEx"));
|
|
__leave;
|
|
}
|
|
|
|
if (!IsmCreateObjectStringsFromHandle (
|
|
DestinationOperationData->String,
|
|
&destNode,
|
|
&destLeaf
|
|
)) {
|
|
DEBUGMSG ((DBG_ERROR, "Can't split dest object in FilterV1MoveEx"));
|
|
__leave;
|
|
}
|
|
|
|
MYASSERT (destNode);
|
|
|
|
if (!destNode) {
|
|
DEBUGMSG ((DBG_ERROR, "Destination spec must be a node"));
|
|
__leave;
|
|
}
|
|
|
|
//
|
|
// Split the source object into node and leaf
|
|
//
|
|
|
|
if (!IsmCreateObjectStringsFromHandle (
|
|
InputData->CurrentObject.ObjectName,
|
|
&srcNode,
|
|
&srcLeaf
|
|
)) {
|
|
DEBUGMSG ((DBG_ERROR, "Can't split v1 src object in FilterV1MoveEx"));
|
|
__leave;
|
|
}
|
|
|
|
if (!srcNode) {
|
|
MYASSERT (FALSE);
|
|
__leave;
|
|
}
|
|
|
|
//
|
|
// If not a local path, do not process
|
|
//
|
|
|
|
if (!_istalpha ((CHARTYPE) _tcsnextc (srcNode)) ||
|
|
_tcsnextc (srcNode + 1) != TEXT(':')
|
|
) {
|
|
DEBUGMSG ((DBG_WARNING, "Ignoring %s\\%s because it does not have a drive spec", srcNode, srcLeaf));
|
|
__leave;
|
|
}
|
|
|
|
ch = (CHARTYPE) _tcsnextc (srcNode + 2);
|
|
|
|
if (ch && ch != TEXT('\\')) {
|
|
DEBUGMSG ((DBG_WARNING, "Ignoring %s\\%s because it does not have a drive spec (2)", srcNode, srcLeaf));
|
|
__leave;
|
|
}
|
|
|
|
// let's see if the current name has something in common
|
|
// with SourceOperationData->String. If so, get the extra part
|
|
// and add it to the destNode
|
|
|
|
//
|
|
// Split the original rule source object into node and leaf
|
|
//
|
|
if (SourceOperationData) {
|
|
|
|
if (IsmCreateObjectStringsFromHandle (
|
|
SourceOperationData->String,
|
|
&orgSrcNode,
|
|
&orgSrcLeaf
|
|
)) {
|
|
if (orgSrcNode) {
|
|
if (StringIPrefix (srcNode, orgSrcNode)) {
|
|
destNodePtr = srcNode + TcharCount (orgSrcNode);
|
|
if (destNodePtr && *destNodePtr) {
|
|
if (_tcsnextc (destNodePtr) == TEXT('\\')) {
|
|
destNodePtr = _tcsinc (destNodePtr);
|
|
}
|
|
if (destNodePtr) {
|
|
newDestNode = JoinPaths (destNode, destNodePtr);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!newDestNode) {
|
|
newDestNode = destNode;
|
|
}
|
|
|
|
//
|
|
// Expand the destination
|
|
//
|
|
MappingSearchAndReplaceEx (
|
|
g_DestEnvMap,
|
|
newDestNode,
|
|
expDestNode,
|
|
0,
|
|
NULL,
|
|
MAX_PATH,
|
|
STRMAP_FIRST_CHAR_MUST_MATCH,
|
|
NULL,
|
|
NULL
|
|
);
|
|
|
|
ismExpDestNode = IsmExpandEnvironmentString (
|
|
PLATFORM_DESTINATION,
|
|
S_SYSENVVAR_GROUP,
|
|
expDestNode,
|
|
NULL
|
|
);
|
|
|
|
if (destLeaf) {
|
|
MappingSearchAndReplaceEx (
|
|
g_DestEnvMap,
|
|
destLeaf,
|
|
expDestLeaf,
|
|
0,
|
|
NULL,
|
|
MAX_PATH,
|
|
STRMAP_FIRST_CHAR_MUST_MATCH,
|
|
NULL,
|
|
NULL
|
|
);
|
|
ismExpDestLeaf = IsmExpandEnvironmentString (
|
|
PLATFORM_DESTINATION,
|
|
S_SYSENVVAR_GROUP,
|
|
expDestLeaf,
|
|
NULL
|
|
);
|
|
|
|
}
|
|
|
|
if (destLeaf) {
|
|
destHandle = IsmCreateObjectHandle (
|
|
ismExpDestNode?ismExpDestNode:expDestNode,
|
|
ismExpDestLeaf?ismExpDestLeaf:expDestLeaf
|
|
);
|
|
} else {
|
|
destHandle = IsmCreateObjectHandle (
|
|
ismExpDestNode?ismExpDestNode:expDestNode,
|
|
srcLeaf
|
|
);
|
|
}
|
|
|
|
if (ismExpDestNode) {
|
|
IsmReleaseMemory (ismExpDestNode);
|
|
ismExpDestNode = NULL;
|
|
}
|
|
if (ismExpDestLeaf) {
|
|
IsmReleaseMemory (ismExpDestLeaf);
|
|
ismExpDestLeaf = NULL;
|
|
}
|
|
|
|
if (destHandle) {
|
|
OutputData->NewObject.ObjectName = destHandle;
|
|
}
|
|
}
|
|
__finally {
|
|
if (newDestNode && (newDestNode != destNode)) {
|
|
FreePathString (newDestNode);
|
|
newDestNode = NULL;
|
|
}
|
|
IsmDestroyObjectString (orgSrcNode);
|
|
IsmDestroyObjectString (orgSrcLeaf);
|
|
IsmDestroyObjectString (destNode);
|
|
IsmDestroyObjectString (destLeaf);
|
|
IsmDestroyObjectString (srcNode);
|
|
IsmDestroyObjectString (srcLeaf);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
FilterV1Move (
|
|
IN PCMIG_FILTERINPUT InputData,
|
|
OUT PMIG_FILTEROUTPUT OutputData,
|
|
IN BOOL NoRestoreObject,
|
|
IN PCMIG_BLOB SourceOperationData, OPTIONAL
|
|
IN PCMIG_BLOB DestinationOperationData OPTIONAL
|
|
)
|
|
{
|
|
PCTSTR destNode = NULL;
|
|
// NTRAID#NTBUG9-153274-2000/08/01-jimschm Static buffer size
|
|
TCHAR expDest[MAX_PATH * 4];
|
|
PCTSTR destLeaf = NULL;
|
|
PCTSTR srcNode = NULL;
|
|
PCTSTR srcLeaf = NULL;
|
|
PCTSTR pathStart;
|
|
// NTRAID#NTBUG9-153274-2000/08/01-jimschm Static buffer size
|
|
TCHAR pathCopy[MAX_PATH * 4];
|
|
PCTSTR newDestNode = NULL;
|
|
PCTSTR newerDestNode = NULL;
|
|
PCTSTR subPath;
|
|
BOOL b;
|
|
CHARTYPE ch;
|
|
MIG_OBJECTSTRINGHANDLE destHandle;
|
|
|
|
__try {
|
|
|
|
//
|
|
// For v1 compatibility, we support only a transformation from
|
|
// original source to inf-specified destination. Chaining of
|
|
// operations is not allowed (these are restrictions caused by the
|
|
// existing INF syntax).
|
|
//
|
|
|
|
if (!DestinationOperationData) {
|
|
DEBUGMSG ((DBG_ERROR, "Missing dest data in FilterV1Move"));
|
|
__leave;
|
|
}
|
|
|
|
if ((InputData->CurrentObject.ObjectTypeId & (~PLATFORM_MASK)) != g_FileType) {
|
|
DEBUGMSG ((DBG_ERROR, "Unexpected object type in FilterV1Move"));
|
|
__leave;
|
|
}
|
|
|
|
if (!IsmCreateObjectStringsFromHandle (
|
|
DestinationOperationData->String,
|
|
&destNode,
|
|
&destLeaf
|
|
)) {
|
|
DEBUGMSG ((DBG_ERROR, "Can't split dest object in FilterV1Move"));
|
|
__leave;
|
|
}
|
|
|
|
MYASSERT (destNode);
|
|
|
|
if (!destNode) {
|
|
DEBUGMSG ((DBG_ERROR, "Destination spec must be a node"));
|
|
__leave;
|
|
}
|
|
|
|
if (destLeaf) {
|
|
DEBUGMSG ((DBG_WARNING, "Dest leaf specification %s (in %s) ignored", destLeaf, destNode));
|
|
}
|
|
|
|
//
|
|
// Find the longest CSIDL inside InputData. Take that as the base directory,
|
|
// and take the rest as the subdirectory.
|
|
//
|
|
|
|
if (!IsmCreateObjectStringsFromHandle (
|
|
InputData->CurrentObject.ObjectName,
|
|
&srcNode,
|
|
&srcLeaf
|
|
)) {
|
|
DEBUGMSG ((DBG_ERROR, "Can't split v1 src object in FilterV1Move"));
|
|
__leave;
|
|
}
|
|
|
|
if (!srcNode) {
|
|
MYASSERT (FALSE);
|
|
__leave;
|
|
}
|
|
|
|
//
|
|
// If not a local path, do not process
|
|
//
|
|
|
|
if (!_istalpha ((CHARTYPE) _tcsnextc (srcNode)) ||
|
|
_tcsnextc (srcNode + 1) != TEXT(':')
|
|
) {
|
|
DEBUGMSG ((DBG_WARNING, "Ignoring %s\\%s because it does not have a drive spec", srcNode, srcLeaf));
|
|
__leave;
|
|
}
|
|
|
|
ch = (CHARTYPE) _tcsnextc (srcNode + 2);
|
|
|
|
if (ch && ch != TEXT('\\')) {
|
|
DEBUGMSG ((DBG_WARNING, "Ignoring %s\\%s because it does not have a drive spec (2)", srcNode, srcLeaf));
|
|
__leave;
|
|
}
|
|
|
|
//
|
|
// Expand the destination
|
|
//
|
|
b = MappingSearchAndReplaceEx (
|
|
g_DestEnvMap,
|
|
destNode,
|
|
expDest,
|
|
0,
|
|
NULL,
|
|
MAX_PATH,
|
|
STRMAP_FIRST_CHAR_MUST_MATCH,
|
|
NULL,
|
|
NULL
|
|
);
|
|
|
|
//
|
|
// Skip over the drive spec
|
|
//
|
|
|
|
pathStart = srcNode;
|
|
|
|
//
|
|
// Find the longest CSIDL by using the reverse mapping table. This takes
|
|
// our full path spec in pathStart and encodes it with an environment
|
|
// variable.
|
|
//
|
|
|
|
b = MappingSearchAndReplaceEx (
|
|
g_RevEnvMap,
|
|
pathStart,
|
|
pathCopy,
|
|
0,
|
|
NULL,
|
|
ARRAYSIZE(pathCopy),
|
|
STRMAP_FIRST_CHAR_MUST_MATCH|
|
|
STRMAP_RETURN_AFTER_FIRST_REPLACE|
|
|
STRMAP_REQUIRE_WACK_OR_NUL,
|
|
NULL,
|
|
&subPath
|
|
);
|
|
|
|
#ifdef DEBUG
|
|
if (!b) {
|
|
TCHAR debugBuf[MAX_PATH];
|
|
|
|
if (MappingSearchAndReplaceEx (
|
|
g_RevEnvMap,
|
|
pathStart,
|
|
debugBuf,
|
|
0,
|
|
NULL,
|
|
ARRAYSIZE(debugBuf),
|
|
STRMAP_FIRST_CHAR_MUST_MATCH|STRMAP_RETURN_AFTER_FIRST_REPLACE,
|
|
NULL,
|
|
NULL
|
|
)) {
|
|
DEBUGMSG ((DBG_WARNING, "Ignoring conversion: %s -> %s", pathStart, debugBuf));
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if (!b) {
|
|
subPath = pathStart + (UINT) (ch ? 3 : 2);
|
|
*pathCopy = 0;
|
|
} else {
|
|
if (*subPath) {
|
|
MYASSERT (_tcsnextc (subPath) == TEXT('\\'));
|
|
|
|
*(PTSTR) subPath = 0;
|
|
subPath++;
|
|
}
|
|
}
|
|
|
|
//
|
|
// pathCopy gives us the base, with CSIDL_ environment variables (might be an empty string)
|
|
// subPath gives us the subdir (might also be an empty string)
|
|
//
|
|
// append subPath to the destination node
|
|
//
|
|
|
|
if (*subPath) {
|
|
newDestNode = JoinPaths (expDest, subPath);
|
|
} else {
|
|
newDestNode = expDest;
|
|
}
|
|
|
|
destHandle = IsmCreateObjectHandle (newDestNode, srcLeaf);
|
|
|
|
if (destHandle) {
|
|
OutputData->NewObject.ObjectName = destHandle;
|
|
}
|
|
}
|
|
__finally {
|
|
IsmDestroyObjectString (destNode);
|
|
IsmDestroyObjectString (destLeaf);
|
|
IsmDestroyObjectString (srcNode);
|
|
IsmDestroyObjectString (srcLeaf);
|
|
|
|
if (newDestNode != expDest) {
|
|
FreePathString (newDestNode);
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
FilterMove (
|
|
IN PCMIG_FILTERINPUT InputData,
|
|
OUT PMIG_FILTEROUTPUT OutputData,
|
|
IN BOOL NoRestoreObject,
|
|
IN PCMIG_BLOB SourceOperationData, OPTIONAL
|
|
IN PCMIG_BLOB DestinationOperationData OPTIONAL
|
|
)
|
|
{
|
|
PCTSTR srcNode = NULL;
|
|
PCTSTR srcLeaf = NULL;
|
|
PCTSTR baseNode = NULL;
|
|
PCTSTR baseLeaf = NULL;
|
|
PCTSTR destNode = NULL;
|
|
PCTSTR destLeaf = NULL;
|
|
PCTSTR node;
|
|
PCTSTR leaf;
|
|
UINT baseNodeLen;
|
|
|
|
__try {
|
|
//
|
|
// Take InputData, break it into node & leaf, take DestinationOperationData,
|
|
// do the same, then replace InputData's node & leaf as appropriate.
|
|
//
|
|
|
|
if (!SourceOperationData) {
|
|
DEBUGMSG ((DBG_ERROR, "Missing source data in general move operation"));
|
|
__leave;
|
|
}
|
|
|
|
if (!DestinationOperationData) {
|
|
DEBUGMSG ((DBG_ERROR, "Missing destination data in general move operation"));
|
|
__leave;
|
|
}
|
|
|
|
if (!IsmCreateObjectStringsFromHandle (
|
|
InputData->CurrentObject.ObjectName,
|
|
&srcNode,
|
|
&srcLeaf
|
|
)) {
|
|
DEBUGMSG ((DBG_ERROR, "Can't split src object in general move operation"));
|
|
__leave;
|
|
}
|
|
|
|
if (!IsmCreateObjectStringsFromHandle (
|
|
SourceOperationData->String,
|
|
&baseNode,
|
|
&baseLeaf
|
|
)) {
|
|
DEBUGMSG ((DBG_ERROR, "Can't split src object in general move operation"));
|
|
__leave;
|
|
}
|
|
|
|
if (!IsmCreateObjectStringsFromHandle (
|
|
DestinationOperationData->String,
|
|
&destNode,
|
|
&destLeaf
|
|
)) {
|
|
DEBUGMSG ((DBG_ERROR, "Can't split dest object in general move operation"));
|
|
__leave;
|
|
}
|
|
|
|
baseNodeLen = TcharCount (baseNode);
|
|
node = NULL;
|
|
leaf = NULL;
|
|
if (StringIMatchTcharCount (srcNode, baseNode, baseNodeLen)) {
|
|
if (srcNode [baseNodeLen]) {
|
|
node = JoinPaths (destNode, &(srcNode [baseNodeLen]));
|
|
} else {
|
|
node = DuplicatePathString (destNode, 0);
|
|
}
|
|
if (!baseLeaf && !destLeaf) {
|
|
leaf = srcLeaf;
|
|
} else if (baseLeaf && srcLeaf && StringIMatch (srcLeaf, baseLeaf)) {
|
|
leaf = destLeaf?destLeaf:baseLeaf;
|
|
} else if (!baseLeaf && destLeaf) {
|
|
if (srcLeaf) {
|
|
leaf = destLeaf;
|
|
}
|
|
} else {
|
|
FreePathString (node);
|
|
node = NULL;
|
|
}
|
|
}
|
|
|
|
if (node) {
|
|
OutputData->NewObject.ObjectName = IsmCreateObjectHandle (node, leaf);
|
|
FreePathString (node);
|
|
node = NULL;
|
|
}
|
|
}
|
|
__finally {
|
|
IsmDestroyObjectString (srcNode);
|
|
IsmDestroyObjectString (srcLeaf);
|
|
IsmDestroyObjectString (baseNode);
|
|
IsmDestroyObjectString (baseLeaf);
|
|
IsmDestroyObjectString (destNode);
|
|
IsmDestroyObjectString (destLeaf);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
FilterIniMove (
|
|
IN PCMIG_FILTERINPUT InputData,
|
|
OUT PMIG_FILTEROUTPUT OutputData,
|
|
IN BOOL NoRestoreObject,
|
|
IN PCMIG_BLOB SourceOperationData, OPTIONAL
|
|
IN PCMIG_BLOB DestinationOperationData OPTIONAL
|
|
)
|
|
{
|
|
PCTSTR srcNode = NULL;
|
|
PCTSTR srcFile = NULL;
|
|
PTSTR srcSect = NULL;
|
|
PTSTR srcKey = NULL;
|
|
PCTSTR baseNode = NULL;
|
|
PCTSTR baseFile = NULL;
|
|
PTSTR baseSect = NULL;
|
|
PTSTR baseKey = NULL;
|
|
PCTSTR destNode = NULL;
|
|
PCTSTR destFile = NULL;
|
|
PTSTR destSect = NULL;
|
|
PTSTR destKey = NULL;
|
|
UINT baseNodeLen;
|
|
BOOL nodeAlloc = FALSE;
|
|
BOOL fileAlloc = FALSE;
|
|
PCTSTR node = NULL;
|
|
PCTSTR file = NULL;
|
|
PCTSTR destSectKey = NULL;
|
|
PCTSTR destLeaf = NULL;
|
|
MIG_OBJECTSTRINGHANDLE baseNodeHandle = NULL;
|
|
MIG_OBJECTSTRINGHANDLE newBaseNode = NULL;
|
|
PCTSTR tempStr = NULL;
|
|
|
|
__try {
|
|
//
|
|
// Take InputData, break it into node & leaf, take DestinationOperationData,
|
|
// do the same, then replace InputData's node & leaf as appropriate.
|
|
//
|
|
|
|
if (!SourceOperationData) {
|
|
DEBUGMSG ((DBG_ERROR, "Missing source data in general move operation"));
|
|
__leave;
|
|
}
|
|
|
|
if (!DestinationOperationData) {
|
|
DEBUGMSG ((DBG_ERROR, "Missing destination data in general move operation"));
|
|
__leave;
|
|
}
|
|
|
|
if (!IsmCreateObjectStringsFromHandle (
|
|
InputData->CurrentObject.ObjectName,
|
|
&srcNode,
|
|
&srcFile
|
|
)) {
|
|
DEBUGMSG ((DBG_ERROR, "Can't split src object in general move operation"));
|
|
__leave;
|
|
}
|
|
if (srcFile [0] == 0) {
|
|
IsmDestroyObjectString (srcFile);
|
|
srcFile = NULL;
|
|
}
|
|
if (srcFile) {
|
|
srcSect = _tcschr (srcFile, TEXT('\\'));
|
|
if (srcSect) {
|
|
*srcSect = 0;
|
|
srcSect ++;
|
|
srcKey = _tcsrchr (srcSect, TEXT('='));
|
|
if (srcKey) {
|
|
*srcKey = 0;
|
|
srcKey ++;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!srcNode || !srcFile || !srcSect || !srcKey) {
|
|
DEBUGMSG ((DBG_ERROR, "INI src object expected to have node, file, section and key"));
|
|
__leave;
|
|
}
|
|
|
|
if (!IsmCreateObjectStringsFromHandle (
|
|
SourceOperationData->String,
|
|
&baseNode,
|
|
&baseFile
|
|
)) {
|
|
DEBUGMSG ((DBG_ERROR, "Can't split base object in general move operation"));
|
|
__leave;
|
|
}
|
|
if (baseFile [0] == 0) {
|
|
IsmDestroyObjectString (baseFile);
|
|
baseFile = NULL;
|
|
}
|
|
if (baseFile) {
|
|
baseSect = _tcschr (baseFile, TEXT('\\'));
|
|
if (baseSect) {
|
|
*baseSect = 0;
|
|
baseSect ++;
|
|
baseKey = _tcsrchr (baseSect, TEXT('='));
|
|
if (baseKey) {
|
|
*baseKey = 0;
|
|
baseKey ++;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!baseNode) {
|
|
DEBUGMSG ((DBG_ERROR, "INI base object expected to have at least a node"));
|
|
__leave;
|
|
}
|
|
|
|
if (!IsmCreateObjectStringsFromHandle (
|
|
DestinationOperationData->String,
|
|
&destNode,
|
|
&destFile
|
|
)) {
|
|
DEBUGMSG ((DBG_ERROR, "Can't split dest object in general move operation"));
|
|
__leave;
|
|
}
|
|
if (destFile [0] == 0) {
|
|
IsmDestroyObjectString (destFile);
|
|
destFile = NULL;
|
|
}
|
|
if (destFile) {
|
|
destSect = _tcschr (destFile, TEXT('\\'));
|
|
if (destSect) {
|
|
*destSect = 0;
|
|
destSect ++;
|
|
destKey = _tcsrchr (destSect, TEXT('='));
|
|
if (destKey) {
|
|
*destKey = 0;
|
|
destKey ++;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!destNode || (destNode [0] == 0)) {
|
|
// We need to use the src node, there was no specification of
|
|
// the node where the INI file is supposed to end up.
|
|
if (!destFile || (destFile [0] == 0)) {
|
|
// destFile is not specified. Let's filter the whole thing
|
|
baseNodeHandle = IsmCreateObjectHandle (srcNode, srcFile);
|
|
if (baseNodeHandle) {
|
|
newBaseNode = IsmFilterObject (
|
|
g_FileType | PLATFORM_SOURCE,
|
|
baseNodeHandle,
|
|
NULL,
|
|
NULL,
|
|
NULL
|
|
);
|
|
if (newBaseNode) {
|
|
IsmCreateObjectStringsFromHandle (newBaseNode, &node, &file);
|
|
nodeAlloc = TRUE;
|
|
fileAlloc = TRUE;
|
|
IsmDestroyObjectHandle (newBaseNode);
|
|
} else {
|
|
node = srcNode;
|
|
file = srcFile;
|
|
}
|
|
IsmDestroyObjectHandle (baseNodeHandle);
|
|
}
|
|
} else {
|
|
// destFile is explicitely specified. Let's just filter the node
|
|
baseNodeHandle = IsmCreateObjectHandle (srcNode, NULL);
|
|
if (baseNodeHandle) {
|
|
newBaseNode = IsmFilterObject (
|
|
g_FileType | PLATFORM_SOURCE,
|
|
baseNodeHandle,
|
|
NULL,
|
|
NULL,
|
|
NULL
|
|
);
|
|
if (newBaseNode) {
|
|
IsmCreateObjectStringsFromHandle (newBaseNode, &node, &tempStr);
|
|
nodeAlloc = TRUE;
|
|
MYASSERT (!tempStr);
|
|
IsmDestroyObjectString (tempStr);
|
|
IsmDestroyObjectHandle (newBaseNode);
|
|
} else {
|
|
node = IsmDuplicateString (srcNode);
|
|
}
|
|
IsmDestroyObjectHandle (baseNodeHandle);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!node) {
|
|
if (destNode && (destNode [0] != 0)) {
|
|
node = destNode;
|
|
} else {
|
|
node = srcNode;
|
|
}
|
|
}
|
|
|
|
if (!file) {
|
|
if (destFile && (destFile [0] != 0)) {
|
|
file = destFile;
|
|
} else {
|
|
file = srcFile;
|
|
}
|
|
}
|
|
|
|
if (!destSect || (destSect [0] == 0)) {
|
|
destSect = srcSect;
|
|
}
|
|
|
|
if (!destKey || (destKey [0] == 0)) {
|
|
destKey = srcKey;
|
|
}
|
|
|
|
destSectKey = JoinTextEx (NULL, destSect, destKey, TEXT("="), 0, NULL);
|
|
|
|
destLeaf = JoinPaths (file, destSectKey);
|
|
|
|
OutputData->NewObject.ObjectName = IsmCreateObjectHandle (node, destLeaf);
|
|
|
|
FreePathString (destLeaf);
|
|
destLeaf = NULL;
|
|
FreeText (destSectKey);
|
|
destSectKey = NULL;
|
|
}
|
|
__finally {
|
|
IsmDestroyObjectString (srcNode);
|
|
IsmDestroyObjectString (srcFile);
|
|
IsmDestroyObjectString (baseNode);
|
|
IsmDestroyObjectString (baseFile);
|
|
IsmDestroyObjectString (destNode);
|
|
IsmDestroyObjectString (destFile);
|
|
if (fileAlloc) {
|
|
IsmDestroyObjectString (file);
|
|
}
|
|
if (nodeAlloc) {
|
|
IsmDestroyObjectString (node);
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
FilterDelete (
|
|
IN PCMIG_FILTERINPUT InputData,
|
|
OUT PMIG_FILTEROUTPUT OutputData,
|
|
IN BOOL NoRestoreObject,
|
|
IN PCMIG_BLOB SourceOperationData, OPTIONAL
|
|
IN PCMIG_BLOB DestinationOperationData OPTIONAL
|
|
)
|
|
{
|
|
//
|
|
// Mark the output data as deleted. That will be sufficient to
|
|
// cause the object to be deleted (even if it was also marked as
|
|
// "save")
|
|
//
|
|
|
|
OutputData->Deleted = TRUE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
FilterRegAutoFilter (
|
|
IN PCMIG_FILTERINPUT InputData,
|
|
OUT PMIG_FILTEROUTPUT OutputData,
|
|
IN BOOL NoRestoreObject,
|
|
IN PCMIG_BLOB SourceOperationData, OPTIONAL
|
|
IN PCMIG_BLOB DestinationOperationData OPTIONAL
|
|
)
|
|
{
|
|
PCTSTR node = NULL;
|
|
PCTSTR leaf = NULL;
|
|
// NTRAID#NTBUG9-153275-2000/08/01-jimschm Static buffer size
|
|
TCHAR newNode[MAX_PATH * 4];
|
|
TCHAR newLeaf[MAX_PATH * 4];
|
|
BOOL change = FALSE;
|
|
|
|
//
|
|
// Filter the object name
|
|
//
|
|
|
|
IsmCreateObjectStringsFromHandle (
|
|
InputData->CurrentObject.ObjectName,
|
|
&node,
|
|
&leaf
|
|
);
|
|
|
|
if (node) {
|
|
if (MappingSearchAndReplaceEx (
|
|
g_RegNodeFilterMap, // map handle
|
|
node, // source string
|
|
newNode, // dest buffer
|
|
0, // source string bytes (0=unspecified)
|
|
NULL, // dest bytes required
|
|
ARRAYSIZE(newNode), // dest buffer size
|
|
0, // flags
|
|
NULL, // extra data value
|
|
NULL // end of string
|
|
)) {
|
|
IsmDestroyObjectString (node);
|
|
node = newNode;
|
|
change = TRUE;
|
|
}
|
|
}
|
|
|
|
if (leaf) {
|
|
if (MappingSearchAndReplaceEx (
|
|
g_RegLeafFilterMap,
|
|
leaf,
|
|
newLeaf,
|
|
0,
|
|
NULL,
|
|
ARRAYSIZE(newLeaf),
|
|
0,
|
|
NULL,
|
|
NULL
|
|
)) {
|
|
IsmDestroyObjectString (leaf);
|
|
leaf = newLeaf;
|
|
change = TRUE;
|
|
}
|
|
}
|
|
|
|
if (change) {
|
|
OutputData->NewObject.ObjectName = IsmCreateObjectHandle (node, leaf);
|
|
}
|
|
|
|
if (node != newNode) {
|
|
IsmDestroyObjectString (node);
|
|
}
|
|
|
|
if (leaf != newLeaf) {
|
|
IsmDestroyObjectString (leaf);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
FilterIniAutoFilter (
|
|
IN PCMIG_FILTERINPUT InputData,
|
|
OUT PMIG_FILTEROUTPUT OutputData,
|
|
IN BOOL NoRestoreObject,
|
|
IN PCMIG_BLOB SourceOperationData, OPTIONAL
|
|
IN PCMIG_BLOB DestinationOperationData OPTIONAL
|
|
)
|
|
{
|
|
// This function will split the INI object, filter the INI file
|
|
// so we know where it ends up, get section and key through the
|
|
// mapping so they can be potentially changed and rebuild the
|
|
// object name.
|
|
|
|
PCTSTR srcNode = NULL;
|
|
PCTSTR srcFile = NULL;
|
|
PTSTR srcSect = NULL;
|
|
PTSTR srcKey = NULL;
|
|
PCTSTR newNode = NULL;
|
|
PCTSTR newFile = NULL;
|
|
PCTSTR newSect = NULL;
|
|
PCTSTR newKey = NULL;
|
|
// NTRAID#NTBUG9-153275-2000/08/01-jimschm Static buffer size
|
|
TCHAR sectBuff [MAXINISIZE];
|
|
TCHAR keyBuff [MAXINISIZE];
|
|
MIG_OBJECTSTRINGHANDLE iniFile = NULL;
|
|
MIG_OBJECTSTRINGHANDLE newIniFile = NULL;
|
|
PCTSTR sectKey = NULL;
|
|
PCTSTR newLeaf = NULL;
|
|
BOOL orgDeleted = FALSE;
|
|
BOOL orgReplaced = FALSE;
|
|
BOOL change = FALSE;
|
|
|
|
//
|
|
// Filter the object name
|
|
//
|
|
|
|
IsmCreateObjectStringsFromHandle (
|
|
InputData->CurrentObject.ObjectName,
|
|
&srcNode,
|
|
&srcFile
|
|
);
|
|
|
|
if (srcNode && srcFile) {
|
|
srcSect = _tcschr (srcFile, TEXT('\\'));
|
|
if (srcSect) {
|
|
*srcSect = 0;
|
|
srcSect ++;
|
|
srcKey = _tcsrchr (srcSect, TEXT('='));
|
|
if (srcKey) {
|
|
*srcKey = 0;
|
|
srcKey ++;
|
|
// let's see if the section is replaced
|
|
if (MappingSearchAndReplaceEx (
|
|
g_IniSectFilterMap, // map handle
|
|
srcSect, // source string
|
|
sectBuff, // dest buffer
|
|
0, // source string bytes (0=unspecified)
|
|
NULL, // dest bytes required
|
|
ARRAYSIZE(sectBuff), // dest buffer size
|
|
0, // flags
|
|
NULL, // extra data value
|
|
NULL // end of string
|
|
)) {
|
|
newSect = sectBuff;
|
|
change = TRUE;
|
|
}
|
|
// let's see if the key is replaced
|
|
if (MappingSearchAndReplaceEx (
|
|
g_IniSectFilterMap, // map handle
|
|
srcKey, // source string
|
|
keyBuff, // dest buffer
|
|
0, // source string bytes (0=unspecified)
|
|
NULL, // dest bytes required
|
|
ARRAYSIZE(keyBuff), // dest buffer size
|
|
0, // flags
|
|
NULL, // extra data value
|
|
NULL // end of string
|
|
)) {
|
|
newKey = keyBuff;
|
|
change = TRUE;
|
|
}
|
|
|
|
iniFile = IsmCreateObjectHandle (srcNode, srcFile);
|
|
if (iniFile) {
|
|
newIniFile = IsmFilterObject (
|
|
g_FileType | PLATFORM_SOURCE,
|
|
iniFile,
|
|
NULL,
|
|
&orgDeleted,
|
|
&orgReplaced
|
|
);
|
|
if (newIniFile) {
|
|
if (IsmCreateObjectStringsFromHandle (newIniFile, &newNode, &newFile)) {
|
|
change = TRUE;
|
|
}
|
|
IsmDestroyObjectHandle (newIniFile);
|
|
}
|
|
IsmDestroyObjectHandle (iniFile);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (change) {
|
|
sectKey = JoinTextEx (NULL, newSect?newSect:srcSect, newKey?newKey:srcKey, TEXT("="), 0, NULL);
|
|
if (sectKey) {
|
|
newLeaf = JoinPaths (newFile?newFile:srcFile, sectKey);
|
|
if (newLeaf) {
|
|
OutputData->NewObject.ObjectName = IsmCreateObjectHandle (newNode?newNode:srcNode, newLeaf);
|
|
FreePathString (newLeaf);
|
|
newLeaf = NULL;
|
|
}
|
|
FreeText (sectKey);
|
|
sectKey = NULL;
|
|
}
|
|
}
|
|
|
|
IsmDestroyObjectString (srcNode);
|
|
IsmDestroyObjectString (srcFile);
|
|
if (newNode) {
|
|
IsmDestroyObjectString (newNode);
|
|
newNode = NULL;
|
|
}
|
|
if (newFile) {
|
|
IsmDestroyObjectString (newFile);
|
|
newFile = NULL;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
pOpmFindFile (
|
|
IN PCTSTR FileName
|
|
)
|
|
{
|
|
MIG_OBJECTSTRINGHANDLE objectName;
|
|
PTSTR node, leaf, leafPtr;
|
|
BOOL result = FALSE;
|
|
|
|
objectName = IsmCreateObjectHandle (FileName, NULL);
|
|
if (objectName) {
|
|
if (IsmGetObjectIdFromName (MIG_FILE_TYPE | PLATFORM_SOURCE, objectName, TRUE) != 0) {
|
|
result = TRUE;
|
|
}
|
|
IsmDestroyObjectHandle (objectName);
|
|
}
|
|
if (!result) {
|
|
node = DuplicateText (FileName);
|
|
leaf = _tcsrchr (node, TEXT('\\'));
|
|
if (leaf) {
|
|
leafPtr = (PTSTR) leaf;
|
|
leaf = _tcsinc (leaf);
|
|
*leafPtr = 0;
|
|
objectName = IsmCreateObjectHandle (node, leaf);
|
|
if (objectName) {
|
|
if (IsmGetObjectIdFromName (MIG_FILE_TYPE | PLATFORM_SOURCE, objectName, TRUE) != 0) {
|
|
result = TRUE;
|
|
}
|
|
IsmDestroyObjectHandle (objectName);
|
|
}
|
|
*leafPtr = TEXT('\\');
|
|
}
|
|
FreeText (node);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
BOOL
|
|
pOpmSearchPath (
|
|
IN PCTSTR FileName,
|
|
IN DWORD BufferLength,
|
|
OUT PTSTR Buffer
|
|
)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
MIG_OBJECTSTRINGHANDLE
|
|
pSimpleTryHandle (
|
|
IN PCTSTR FullPath
|
|
)
|
|
{
|
|
PCTSTR buffer;
|
|
PTSTR leafPtr, leaf;
|
|
MIG_OBJECTSTRINGHANDLE source = NULL;
|
|
MIG_OBJECTSTRINGHANDLE result = NULL;
|
|
PTSTR workingPath;
|
|
PCTSTR sanitizedPath;
|
|
BOOL orgDeleted = FALSE;
|
|
BOOL orgReplaced = FALSE;
|
|
PCTSTR saved = NULL;
|
|
|
|
sanitizedPath = SanitizePath (FullPath);
|
|
if (!sanitizedPath) {
|
|
return NULL;
|
|
}
|
|
|
|
source = IsmCreateObjectHandle (sanitizedPath, NULL);
|
|
if (source) {
|
|
result = IsmFilterObject (
|
|
g_FileType | PLATFORM_SOURCE,
|
|
source,
|
|
NULL,
|
|
&orgDeleted,
|
|
&orgReplaced
|
|
);
|
|
// we do not want replaced directories
|
|
// since they can be false hits
|
|
if (orgDeleted) {
|
|
if (result) {
|
|
saved = result;
|
|
result = NULL;
|
|
}
|
|
}
|
|
if (!result && !orgDeleted) {
|
|
result = source;
|
|
} else {
|
|
IsmDestroyObjectHandle (source);
|
|
source = NULL;
|
|
}
|
|
}
|
|
|
|
if (result) {
|
|
goto exit;
|
|
}
|
|
|
|
buffer = DuplicatePathString (sanitizedPath, 0);
|
|
|
|
leaf = _tcsrchr (buffer, TEXT('\\'));
|
|
|
|
if (leaf) {
|
|
leafPtr = leaf;
|
|
leaf = _tcsinc (leaf);
|
|
*leafPtr = 0;
|
|
source = IsmCreateObjectHandle (buffer, leaf);
|
|
*leafPtr = TEXT('\\');
|
|
}
|
|
|
|
FreePathString (buffer);
|
|
|
|
if (source) {
|
|
result = IsmFilterObject (
|
|
g_FileType | PLATFORM_SOURCE,
|
|
source,
|
|
NULL,
|
|
&orgDeleted,
|
|
&orgReplaced
|
|
);
|
|
if (!result && !orgDeleted) {
|
|
result = source;
|
|
} else {
|
|
if (!result) {
|
|
result = saved;
|
|
}
|
|
IsmDestroyObjectHandle (source);
|
|
source = NULL;
|
|
}
|
|
}
|
|
|
|
if (result != saved) {
|
|
IsmDestroyObjectHandle (saved);
|
|
saved = NULL;
|
|
}
|
|
|
|
exit:
|
|
FreePathString (sanitizedPath);
|
|
return result;
|
|
}
|
|
|
|
MIG_OBJECTSTRINGHANDLE
|
|
pTryHandle (
|
|
IN PCTSTR FullPath,
|
|
IN PCTSTR Hint,
|
|
OUT PCTSTR *TrimmedResult
|
|
)
|
|
{
|
|
PATH_ENUM pathEnum;
|
|
PCTSTR newPath;
|
|
MIG_OBJECTSTRINGHANDLE result = NULL;
|
|
PCTSTR nativeName = NULL;
|
|
PCTSTR lastSegPtr;
|
|
|
|
if (TrimmedResult) {
|
|
*TrimmedResult = NULL;
|
|
}
|
|
|
|
result = pSimpleTryHandle (FullPath);
|
|
if (result || (!Hint)) {
|
|
return result;
|
|
}
|
|
if (EnumFirstPathEx (&pathEnum, Hint, NULL, NULL, FALSE)) {
|
|
do {
|
|
newPath = JoinPaths (pathEnum.PtrCurrPath, FullPath);
|
|
result = pSimpleTryHandle (newPath);
|
|
if (result) {
|
|
AbortPathEnum (&pathEnum);
|
|
FreePathString (newPath);
|
|
// now, if the initial FullPath did not have any wack in it
|
|
// we will take the last segment of the result and put it
|
|
// in TrimmedResult
|
|
if (TrimmedResult && (!_tcschr (FullPath, TEXT('\\')))) {
|
|
nativeName = IsmGetNativeObjectName (g_FileType, result);
|
|
if (nativeName) {
|
|
lastSegPtr = _tcsrchr (nativeName, TEXT('\\'));
|
|
if (lastSegPtr) {
|
|
lastSegPtr = _tcsinc (lastSegPtr);
|
|
if (lastSegPtr) {
|
|
*TrimmedResult = DuplicatePathString (lastSegPtr, 0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
FreePathString (newPath);
|
|
} while (EnumNextPath (&pathEnum));
|
|
}
|
|
AbortPathEnum (&pathEnum);
|
|
return NULL;
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
DoRegAutoFilter (
|
|
IN MIG_OBJECTTYPEID SrcObjectTypeId,
|
|
IN MIG_OBJECTSTRINGHANDLE SrcObjectName,
|
|
IN PCMIG_CONTENT OriginalContent,
|
|
IN PCMIG_CONTENT CurrentContent,
|
|
OUT PMIG_CONTENT NewContent,
|
|
IN PCMIG_BLOB SourceOperationData, OPTIONAL
|
|
IN PCMIG_BLOB DestinationOperationData OPTIONAL
|
|
)
|
|
{
|
|
PTSTR leafPtr = NULL;
|
|
PDWORD valueType;
|
|
MIG_OBJECTSTRINGHANDLE source;
|
|
MIG_OBJECTSTRINGHANDLE destination;
|
|
PCTSTR leaf;
|
|
TCHAR expandBuffer[4096];
|
|
TCHAR hintBuffer[4096];
|
|
PTSTR buffer;
|
|
GROWBUFFER result = INIT_GROWBUFFER;
|
|
GROWBUFFER cmdLineBuffer = INIT_GROWBUFFER;
|
|
PCMDLINE cmdLine;
|
|
UINT u;
|
|
PCTSTR data, p, end;
|
|
PCTSTR nativeDest;
|
|
PCTSTR newData, oldData;
|
|
BOOL parsable;
|
|
BOOL replaced = FALSE;
|
|
BOOL orgDeleted = FALSE;
|
|
BOOL orgReplaced = FALSE;
|
|
PCTSTR trimmedResult = NULL;
|
|
BOOL newContent = TRUE;
|
|
PCTSTR destResult = NULL;
|
|
|
|
//
|
|
// Filter the data for any references to %windir%
|
|
//
|
|
|
|
if (!CurrentContent->ContentInFile) {
|
|
|
|
parsable = FALSE;
|
|
valueType = (PDWORD)(CurrentContent->Details.DetailsData);
|
|
if (valueType) {
|
|
if (*valueType == REG_EXPAND_SZ ||
|
|
*valueType == REG_SZ
|
|
) {
|
|
|
|
parsable = TRUE;
|
|
}
|
|
} else {
|
|
parsable = IsmIsObjectHandleNodeOnly (SrcObjectName);
|
|
}
|
|
|
|
if (parsable) {
|
|
|
|
data = (PTSTR) CurrentContent->MemoryContent.ContentBytes;
|
|
end = (PCTSTR) (CurrentContent->MemoryContent.ContentBytes + CurrentContent->MemoryContent.ContentSize);
|
|
|
|
while (data < end) {
|
|
if (*data == 0) {
|
|
break;
|
|
}
|
|
|
|
data = _tcsinc (data);
|
|
}
|
|
|
|
if (data >= end) {
|
|
parsable = FALSE;
|
|
}
|
|
}
|
|
|
|
if (parsable) {
|
|
|
|
data = (PTSTR) CurrentContent->MemoryContent.ContentBytes;
|
|
|
|
if ((*valueType == REG_EXPAND_SZ) ||
|
|
(*valueType == REG_SZ)
|
|
) {
|
|
//
|
|
// Expand the data
|
|
//
|
|
|
|
MappingSearchAndReplaceEx (
|
|
g_EnvMap,
|
|
data,
|
|
expandBuffer,
|
|
0,
|
|
NULL,
|
|
ARRAYSIZE(expandBuffer),
|
|
0,
|
|
NULL,
|
|
NULL
|
|
);
|
|
|
|
data = expandBuffer;
|
|
}
|
|
|
|
*hintBuffer = 0;
|
|
if (DestinationOperationData &&
|
|
(DestinationOperationData->Type == BLOBTYPE_STRING) &&
|
|
(DestinationOperationData->String)
|
|
) {
|
|
MappingSearchAndReplaceEx (
|
|
g_EnvMap,
|
|
DestinationOperationData->String,
|
|
hintBuffer,
|
|
0,
|
|
NULL,
|
|
ARRAYSIZE(hintBuffer),
|
|
0,
|
|
NULL,
|
|
NULL
|
|
);
|
|
}
|
|
|
|
destination = pTryHandle (data, *hintBuffer?hintBuffer:NULL, &trimmedResult);
|
|
|
|
if (destination) {
|
|
replaced = TRUE;
|
|
if (trimmedResult) {
|
|
GbAppendString (&result, trimmedResult);
|
|
FreePathString (trimmedResult);
|
|
} else {
|
|
nativeDest = IsmGetNativeObjectName (g_FileType, destination);
|
|
GbAppendString (&result, nativeDest);
|
|
IsmReleaseMemory (nativeDest);
|
|
}
|
|
}
|
|
|
|
// finally, if we failed we are going to assume it's a command line
|
|
if (!replaced) {
|
|
newData = DuplicatePathString (data, 0);
|
|
cmdLine = ParseCmdLineEx (data, NULL, &pOpmFindFile, &pOpmSearchPath, &cmdLineBuffer);
|
|
if (cmdLine) {
|
|
|
|
//
|
|
// Find the file referenced in the list or command line
|
|
//
|
|
for (u = 0 ; u < cmdLine->ArgCount ; u++) {
|
|
p = cmdLine->Args[u].CleanedUpArg;
|
|
|
|
// first we try it as is
|
|
|
|
destination = pTryHandle (p, *hintBuffer?hintBuffer:NULL, &trimmedResult);
|
|
|
|
// maybe we have something like /m:c:\foo.txt
|
|
// we need to go forward until we find a sequence of
|
|
// <alpha>:\<something>
|
|
if (!destination && p[0] && p[1]) {
|
|
|
|
while (p[2]) {
|
|
if (_istalpha ((CHARTYPE) _tcsnextc (p)) &&
|
|
p[1] == TEXT(':') &&
|
|
p[2] == TEXT('\\')
|
|
) {
|
|
|
|
destination = pTryHandle (p, *hintBuffer?hintBuffer:NULL, &trimmedResult);
|
|
|
|
if (destination) {
|
|
break;
|
|
}
|
|
}
|
|
p ++;
|
|
}
|
|
}
|
|
if (destination) {
|
|
replaced = TRUE;
|
|
if (trimmedResult) {
|
|
oldData = StringSearchAndReplace (newData, p, trimmedResult);
|
|
if (oldData) {
|
|
FreePathString (newData);
|
|
newData = oldData;
|
|
}
|
|
FreePathString (trimmedResult);
|
|
} else {
|
|
nativeDest = IsmGetNativeObjectName (g_FileType, destination);
|
|
oldData = StringSearchAndReplace (newData, p, nativeDest);
|
|
if (oldData) {
|
|
FreePathString (newData);
|
|
newData = oldData;
|
|
}
|
|
IsmReleaseMemory (nativeDest);
|
|
}
|
|
IsmDestroyObjectHandle (destination);
|
|
destination = NULL;
|
|
}
|
|
}
|
|
}
|
|
GbFree (&cmdLineBuffer);
|
|
if (!replaced) {
|
|
if (newData) {
|
|
FreePathString (newData);
|
|
}
|
|
} else {
|
|
if (newData) {
|
|
GbAppendString (&result, newData);
|
|
FreePathString (newData);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (destination) {
|
|
IsmDestroyObjectHandle (destination);
|
|
destination = NULL;
|
|
}
|
|
|
|
if (replaced && result.Buf) {
|
|
// looks like we have new content
|
|
// Let's do one more check. If this is a REG_EXPAND_SZ we will do our best to
|
|
// keep the stuff unexpanded. So if the source string expanded on the destination
|
|
// machine is the same as the destination string we won't do anything.
|
|
newContent = TRUE;
|
|
if (*valueType == REG_EXPAND_SZ) {
|
|
destResult = IsmExpandEnvironmentString (
|
|
PLATFORM_DESTINATION,
|
|
S_SYSENVVAR_GROUP,
|
|
(PCTSTR) CurrentContent->MemoryContent.ContentBytes,
|
|
NULL
|
|
);
|
|
if (destResult && StringIMatch (destResult, (PCTSTR)result.Buf)) {
|
|
newContent = FALSE;
|
|
}
|
|
if (destResult) {
|
|
IsmReleaseMemory (destResult);
|
|
destResult = NULL;
|
|
}
|
|
}
|
|
if (newContent) {
|
|
NewContent->MemoryContent.ContentSize = SizeOfString ((PCTSTR)result.Buf);
|
|
NewContent->MemoryContent.ContentBytes = IsmGetMemory (NewContent->MemoryContent.ContentSize);
|
|
CopyMemory ((PTSTR)NewContent->MemoryContent.ContentBytes, result.Buf, NewContent->MemoryContent.ContentSize);
|
|
}
|
|
}
|
|
|
|
GbFree (&result);
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
DoIniAutoFilter (
|
|
IN MIG_OBJECTTYPEID SrcObjectTypeId,
|
|
IN MIG_OBJECTSTRINGHANDLE SrcObjectName,
|
|
IN PCMIG_CONTENT OriginalContent,
|
|
IN PCMIG_CONTENT CurrentContent,
|
|
OUT PMIG_CONTENT NewContent,
|
|
IN PCMIG_BLOB SourceOperationData, OPTIONAL
|
|
IN PCMIG_BLOB DestinationOperationData OPTIONAL
|
|
)
|
|
{
|
|
// This function will get the content of an INI key and see if there is
|
|
// a path there somewhere. If yes, it will attempt to find the new
|
|
// location for the file and replace it in the INI key content.
|
|
|
|
PTSTR leafPtr = NULL;
|
|
PDWORD valueType;
|
|
MIG_OBJECTSTRINGHANDLE source;
|
|
MIG_OBJECTSTRINGHANDLE destination;
|
|
PCTSTR leaf;
|
|
TCHAR expandBuffer[4096];
|
|
TCHAR hintBuffer[4096];
|
|
PTSTR buffer;
|
|
GROWBUFFER result = INIT_GROWBUFFER;
|
|
GROWBUFFER cmdLineBuffer = INIT_GROWBUFFER;
|
|
PCMDLINE cmdLine;
|
|
UINT u;
|
|
PCTSTR data, p, end;
|
|
PCTSTR nativeDest;
|
|
PCTSTR newData, oldData;
|
|
BOOL parsable;
|
|
BOOL replaced = FALSE;
|
|
BOOL orgDeleted = FALSE;
|
|
BOOL orgReplaced = FALSE;
|
|
PCTSTR trimmedResult = NULL;
|
|
BOOL newContent = TRUE;
|
|
PCTSTR destResult = NULL;
|
|
|
|
//
|
|
// Filter the data for any references to %windir%
|
|
//
|
|
|
|
if (!CurrentContent->ContentInFile) {
|
|
|
|
data = (PTSTR) CurrentContent->MemoryContent.ContentBytes;
|
|
end = (PCTSTR) (CurrentContent->MemoryContent.ContentBytes + CurrentContent->MemoryContent.ContentSize);
|
|
|
|
parsable = TRUE;
|
|
|
|
while (data < end) {
|
|
if (*data == 0) {
|
|
break;
|
|
}
|
|
|
|
data = _tcsinc (data);
|
|
}
|
|
|
|
if (data >= end) {
|
|
parsable = FALSE;
|
|
}
|
|
|
|
if (parsable) {
|
|
|
|
data = (PTSTR) CurrentContent->MemoryContent.ContentBytes;
|
|
|
|
MappingSearchAndReplaceEx (
|
|
g_EnvMap,
|
|
data,
|
|
expandBuffer,
|
|
0,
|
|
NULL,
|
|
ARRAYSIZE(expandBuffer),
|
|
0,
|
|
NULL,
|
|
NULL
|
|
);
|
|
|
|
data = expandBuffer;
|
|
|
|
*hintBuffer = 0;
|
|
if (DestinationOperationData &&
|
|
(DestinationOperationData->Type == BLOBTYPE_STRING) &&
|
|
(DestinationOperationData->String)
|
|
) {
|
|
MappingSearchAndReplaceEx (
|
|
g_EnvMap,
|
|
DestinationOperationData->String,
|
|
hintBuffer,
|
|
0,
|
|
NULL,
|
|
ARRAYSIZE(hintBuffer),
|
|
0,
|
|
NULL,
|
|
NULL
|
|
);
|
|
}
|
|
|
|
destination = pTryHandle (data, *hintBuffer?hintBuffer:NULL, &trimmedResult);
|
|
|
|
if (destination) {
|
|
replaced = TRUE;
|
|
if (trimmedResult) {
|
|
GbAppendString (&result, trimmedResult);
|
|
FreePathString (trimmedResult);
|
|
} else {
|
|
nativeDest = IsmGetNativeObjectName (g_FileType, destination);
|
|
GbAppendString (&result, nativeDest);
|
|
IsmReleaseMemory (nativeDest);
|
|
}
|
|
}
|
|
|
|
// finally, if we failed we are going to assume it's a command line
|
|
if (!replaced) {
|
|
newData = DuplicatePathString (data, 0);
|
|
cmdLine = ParseCmdLineEx (data, NULL, &pOpmFindFile, &pOpmSearchPath, &cmdLineBuffer);
|
|
if (cmdLine) {
|
|
|
|
//
|
|
// Find the file referenced in the list or command line
|
|
//
|
|
for (u = 0 ; u < cmdLine->ArgCount ; u++) {
|
|
p = cmdLine->Args[u].CleanedUpArg;
|
|
|
|
// first we try it as is
|
|
|
|
destination = pTryHandle (p, *hintBuffer?hintBuffer:NULL, &trimmedResult);
|
|
|
|
// maybe we have something like /m:c:\foo.txt
|
|
// we need to go forward until we find a sequence of
|
|
// <alpha>:\<something>
|
|
if (!destination && p[0] && p[1]) {
|
|
|
|
while (p[2]) {
|
|
if (_istalpha ((CHARTYPE) _tcsnextc (p)) &&
|
|
p[1] == TEXT(':') &&
|
|
p[2] == TEXT('\\')
|
|
) {
|
|
|
|
destination = pTryHandle (p, *hintBuffer?hintBuffer:NULL, &trimmedResult);
|
|
|
|
if (destination) {
|
|
break;
|
|
}
|
|
}
|
|
p ++;
|
|
}
|
|
}
|
|
if (destination) {
|
|
replaced = TRUE;
|
|
if (trimmedResult) {
|
|
oldData = StringSearchAndReplace (newData, p, trimmedResult);
|
|
if (oldData) {
|
|
FreePathString (newData);
|
|
newData = oldData;
|
|
}
|
|
FreePathString (trimmedResult);
|
|
} else {
|
|
nativeDest = IsmGetNativeObjectName (g_FileType, destination);
|
|
oldData = StringSearchAndReplace (newData, p, nativeDest);
|
|
if (oldData) {
|
|
FreePathString (newData);
|
|
newData = oldData;
|
|
}
|
|
IsmReleaseMemory (nativeDest);
|
|
}
|
|
IsmDestroyObjectHandle (destination);
|
|
destination = NULL;
|
|
}
|
|
}
|
|
}
|
|
GbFree (&cmdLineBuffer);
|
|
if (!replaced) {
|
|
if (newData) {
|
|
FreePathString (newData);
|
|
}
|
|
} else {
|
|
if (newData) {
|
|
GbAppendString (&result, newData);
|
|
FreePathString (newData);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (destination) {
|
|
IsmDestroyObjectHandle (destination);
|
|
destination = NULL;
|
|
}
|
|
|
|
if (replaced && result.Buf) {
|
|
// looks like we have new content
|
|
// Let's do one more check. If the source string has environment variables in it,
|
|
// we will do our best to keep the stuff unexpanded. So if the source string
|
|
// expanded on the destination machine is the same as the destination string
|
|
// we won't do anything.
|
|
newContent = TRUE;
|
|
destResult = IsmExpandEnvironmentString (
|
|
PLATFORM_DESTINATION,
|
|
S_SYSENVVAR_GROUP,
|
|
(PCTSTR) CurrentContent->MemoryContent.ContentBytes,
|
|
NULL
|
|
);
|
|
if (destResult && StringIMatch (destResult, (PCTSTR)result.Buf)) {
|
|
newContent = FALSE;
|
|
}
|
|
if (destResult) {
|
|
IsmReleaseMemory (destResult);
|
|
destResult = NULL;
|
|
}
|
|
if (newContent) {
|
|
NewContent->MemoryContent.ContentSize = SizeOfString ((PCTSTR)result.Buf);
|
|
NewContent->MemoryContent.ContentBytes = IsmGetMemory (NewContent->MemoryContent.ContentSize);
|
|
CopyMemory ((PTSTR)NewContent->MemoryContent.ContentBytes, result.Buf, NewContent->MemoryContent.ContentSize);
|
|
}
|
|
}
|
|
|
|
GbFree (&result);
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
DoFixDefaultIcon (
|
|
IN MIG_OBJECTTYPEID SrcObjectTypeId,
|
|
IN MIG_OBJECTSTRINGHANDLE SrcObjectName,
|
|
IN PCMIG_CONTENT OriginalContent,
|
|
IN PCMIG_CONTENT CurrentContent,
|
|
OUT PMIG_CONTENT NewContent,
|
|
IN PCMIG_BLOB SourceOperationData, OPTIONAL
|
|
IN PCMIG_BLOB DestinationOperationData OPTIONAL
|
|
)
|
|
{
|
|
MIG_PROPERTYDATAID propDataId;
|
|
MIG_BLOBTYPE propDataType;
|
|
UINT requiredSize;
|
|
PDWORD valueType;
|
|
PICON_GROUP iconGroup = NULL;
|
|
ICON_SGROUP iconSGroup = {0, NULL};
|
|
PTSTR iconLibPath = NULL;
|
|
INT iconNumber = 0;
|
|
PTSTR dataCopy;
|
|
|
|
if (CurrentContent->ContentInFile) {
|
|
return TRUE;
|
|
}
|
|
valueType = (PDWORD)(CurrentContent->Details.DetailsData);
|
|
if (*valueType != REG_SZ && *valueType != REG_EXPAND_SZ) {
|
|
return TRUE;
|
|
}
|
|
// let's see if we have our property attached
|
|
propDataId = IsmGetPropertyFromObject (SrcObjectTypeId, SrcObjectName, g_DefaultIconData);
|
|
if (!propDataId) {
|
|
return TRUE;
|
|
}
|
|
if (!IsmGetPropertyData (propDataId, NULL, 0, &requiredSize, &propDataType)) {
|
|
return TRUE;
|
|
}
|
|
iconSGroup.DataSize = requiredSize;
|
|
iconSGroup.Data = IsmGetMemory (requiredSize);
|
|
if (!IsmGetPropertyData (propDataId, (PBYTE)iconSGroup.Data, requiredSize, NULL, &propDataType)) {
|
|
IsmReleaseMemory (iconSGroup.Data);
|
|
return TRUE;
|
|
}
|
|
if (!iconSGroup.DataSize) {
|
|
IsmReleaseMemory (iconSGroup.Data);
|
|
return TRUE;
|
|
}
|
|
iconGroup = IcoDeSerializeIconGroup (&iconSGroup);
|
|
if (!iconGroup) {
|
|
IsmReleaseMemory (iconSGroup.Data);
|
|
return TRUE;
|
|
}
|
|
if (IsmGetEnvironmentString (
|
|
PLATFORM_DESTINATION,
|
|
NULL,
|
|
S_ENV_ICONLIB,
|
|
NULL,
|
|
0,
|
|
&requiredSize
|
|
)) {
|
|
iconLibPath = IsmGetMemory (requiredSize);
|
|
if (IsmGetEnvironmentString (
|
|
PLATFORM_DESTINATION,
|
|
NULL,
|
|
S_ENV_ICONLIB,
|
|
iconLibPath,
|
|
requiredSize,
|
|
NULL
|
|
)) {
|
|
if (IcoWriteIconGroupToPeFile (iconLibPath, iconGroup, NULL, &iconNumber)) {
|
|
// finally we wrote the icon, fix the content and tell scanstate that
|
|
// we iconlib was used
|
|
dataCopy = IsmGetMemory (SizeOfString (iconLibPath) + sizeof (TCHAR) + 20 * sizeof (TCHAR));
|
|
wsprintf (dataCopy, TEXT("%s,%d"), iconLibPath, iconNumber);
|
|
NewContent->MemoryContent.ContentSize = SizeOfString (dataCopy);
|
|
NewContent->MemoryContent.ContentBytes = (PBYTE) dataCopy;
|
|
IsmSetEnvironmentFlag (PLATFORM_DESTINATION, NULL, S_ENV_SAVE_ICONLIB);
|
|
}
|
|
}
|
|
IsmReleaseMemory (iconLibPath);
|
|
}
|
|
IcoReleaseIconGroup (iconGroup);
|
|
IsmReleaseMemory (iconSGroup.Data);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
pDoesDestObjectExist (
|
|
IN MIG_OBJECTSTRINGHANDLE ObjectName
|
|
)
|
|
{
|
|
PCTSTR nativeName;
|
|
BOOL result = FALSE;
|
|
|
|
nativeName = IsmGetNativeObjectName (PLATFORM_DESTINATION | MIG_FILE_TYPE, ObjectName);
|
|
if (nativeName) {
|
|
if (IsmGetRealPlatform () == PLATFORM_DESTINATION) {
|
|
result = DoesFileExist (nativeName);
|
|
}
|
|
IsmReleaseMemory (nativeName);
|
|
nativeName = NULL;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
FilterFileAutoFilter (
|
|
IN PCMIG_FILTERINPUT InputData,
|
|
OUT PMIG_FILTEROUTPUT OutputData,
|
|
IN BOOL NoRestoreObject,
|
|
IN PCMIG_BLOB SourceOperationData, OPTIONAL
|
|
IN PCMIG_BLOB DestinationOperationData OPTIONAL
|
|
)
|
|
{
|
|
PCTSTR node, nodeWack;
|
|
PCTSTR leaf;
|
|
// NTRAID#NTBUG9-153275-2000/08/01-jimschm Static buffer size
|
|
TCHAR newNode[MAX_PATH * 4];
|
|
TCHAR newLeaf[MAX_PATH * 4];
|
|
BOOL fullChanged = FALSE;
|
|
PCTSTR nativeName;
|
|
PTSTR leafPtr;
|
|
BOOL changed = FALSE;
|
|
|
|
if (InputData &&
|
|
InputData->OriginalObject.ObjectName &&
|
|
InputData->CurrentObject.ObjectName &&
|
|
(InputData->OriginalObject.ObjectName != InputData->CurrentObject.ObjectName)
|
|
) {
|
|
// this was already modified. Let's not touch it.
|
|
return TRUE;
|
|
}
|
|
|
|
//
|
|
// Filter the object name
|
|
//
|
|
|
|
IsmCreateObjectStringsFromHandle (
|
|
InputData->CurrentObject.ObjectName,
|
|
&node,
|
|
&leaf
|
|
);
|
|
|
|
/*
|
|
// I am taking this out. The point is,
|
|
// even if we are not restoring the file,
|
|
// we should get the best guess as to where
|
|
// this file would end up in case it would
|
|
// get moved.
|
|
if (NoRestoreObject && leaf) {
|
|
IsmDestroyObjectString (node);
|
|
IsmDestroyObjectString (leaf);
|
|
return TRUE;
|
|
}
|
|
*/
|
|
|
|
if (node && leaf) {
|
|
// let's do a trick here. Let's build the native name and
|
|
// see if we can find an env replacement for the entire
|
|
// path
|
|
nativeName = IsmGetNativeObjectName (InputData->CurrentObject.ObjectTypeId, InputData->CurrentObject.ObjectName);
|
|
if (nativeName) {
|
|
if (MappingSearchAndReplaceEx (
|
|
g_FileNodeFilterMap, // map handle
|
|
nativeName, // source string
|
|
newNode, // dest buffer
|
|
0, // source string bytes (0=unspecified)
|
|
NULL, // dest bytes required
|
|
ARRAYSIZE(newNode), // dest buffer size
|
|
STRMAP_COMPLETE_MATCH_ONLY, // flags
|
|
NULL, // extra data value
|
|
NULL // end of string
|
|
)) {
|
|
// we have a replacement. Let's split it into node and leaf
|
|
leafPtr = _tcsrchr (newNode, TEXT('\\'));
|
|
if (leafPtr) {
|
|
*leafPtr = 0;
|
|
leafPtr ++;
|
|
StringCopy (newLeaf, leafPtr);
|
|
IsmDestroyObjectString (node);
|
|
node = newNode;
|
|
IsmDestroyObjectString (leaf);
|
|
leaf = newLeaf;
|
|
fullChanged = TRUE;
|
|
}
|
|
}
|
|
IsmReleaseMemory (nativeName);
|
|
nativeName = NULL;
|
|
}
|
|
}
|
|
|
|
if (!fullChanged && node) {
|
|
nodeWack = JoinPaths (node, TEXT(""));
|
|
if (MappingSearchAndReplaceEx (
|
|
g_FileNodeFilterMap, // map handle
|
|
nodeWack, // source string
|
|
newNode, // dest buffer
|
|
0, // source string bytes (0=unspecified)
|
|
NULL, // dest bytes required
|
|
ARRAYSIZE(newNode), // dest buffer size
|
|
STRMAP_FIRST_CHAR_MUST_MATCH|
|
|
STRMAP_RETURN_AFTER_FIRST_REPLACE|
|
|
STRMAP_REQUIRE_WACK_OR_NUL, // flags
|
|
NULL, // extra data value
|
|
NULL // end of string
|
|
)) {
|
|
IsmDestroyObjectString (node);
|
|
node = newNode;
|
|
changed = TRUE;
|
|
} else {
|
|
if (MappingSearchAndReplaceEx (
|
|
g_FileNodeFilterMap, // map handle
|
|
node, // source string
|
|
newNode, // dest buffer
|
|
0, // source string bytes (0=unspecified)
|
|
NULL, // dest bytes required
|
|
ARRAYSIZE(newNode), // dest buffer size
|
|
STRMAP_FIRST_CHAR_MUST_MATCH|
|
|
STRMAP_RETURN_AFTER_FIRST_REPLACE|
|
|
STRMAP_REQUIRE_WACK_OR_NUL, // flags
|
|
NULL, // extra data value
|
|
NULL // end of string
|
|
)) {
|
|
IsmDestroyObjectString (node);
|
|
node = newNode;
|
|
changed = TRUE;
|
|
}
|
|
}
|
|
|
|
FreePathString (nodeWack);
|
|
nodeWack = NULL;
|
|
}
|
|
|
|
if (!fullChanged && leaf) {
|
|
if (MappingSearchAndReplaceEx (
|
|
g_FileLeafFilterMap,
|
|
leaf,
|
|
newLeaf,
|
|
0,
|
|
NULL,
|
|
ARRAYSIZE(newLeaf),
|
|
0,
|
|
NULL,
|
|
NULL
|
|
)) {
|
|
IsmDestroyObjectString (leaf);
|
|
leaf = newLeaf;
|
|
changed = TRUE;
|
|
}
|
|
}
|
|
|
|
if (fullChanged || changed) {
|
|
OutputData->NewObject.ObjectName = IsmCreateObjectHandle (node, leaf);
|
|
}
|
|
OutputData->Replaced = (NoRestoreObject||OutputData->Deleted)?pDoesDestObjectExist (OutputData->NewObject.ObjectName):0;
|
|
|
|
if (node != newNode) {
|
|
IsmDestroyObjectString (node);
|
|
}
|
|
|
|
if (leaf != newLeaf) {
|
|
IsmDestroyObjectString (leaf);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
PCTSTR
|
|
pProcessRenameExMacro (
|
|
IN PCTSTR Node,
|
|
IN PCTSTR Leaf, OPTIONAL
|
|
IN BOOL ZeroBase
|
|
)
|
|
{
|
|
PCTSTR workingStr;
|
|
PTSTR macroStartPtr = NULL;
|
|
PTSTR macroEndPtr = NULL;
|
|
PTSTR macroCopy = NULL;
|
|
DWORD macroLength = 0;
|
|
PTSTR macroParsePtr = NULL;
|
|
TCHAR macroBuffer [MAX_PATH];
|
|
HRESULT hr;
|
|
MIG_OBJECTSTRINGHANDLE testHandle = NULL;
|
|
|
|
UINT index;
|
|
PTSTR newString = NULL;
|
|
|
|
// If Leaf is supplied, we are working only on the Leaf
|
|
workingStr = Leaf ? Leaf : Node;
|
|
|
|
// Extract macro
|
|
macroStartPtr = _tcschr (workingStr, S_RENAMEEX_START_CHAR);
|
|
if (macroStartPtr) {
|
|
macroEndPtr = _tcschr (macroStartPtr + 1, S_RENAMEEX_END_CHAR);
|
|
}
|
|
if (macroEndPtr) {
|
|
macroCopy = DuplicateText (macroStartPtr + 1);
|
|
macroCopy[macroEndPtr-macroStartPtr-1] = 0;
|
|
}
|
|
|
|
if (macroCopy) {
|
|
// Build a possible destination
|
|
if (ZeroBase) {
|
|
index = 0;
|
|
} else {
|
|
index = 1;
|
|
}
|
|
|
|
do {
|
|
if (newString) {
|
|
FreeText (newString);
|
|
newString = NULL;
|
|
}
|
|
IsmDestroyObjectHandle (testHandle);
|
|
|
|
__try {
|
|
hr = StringCbPrintf (macroBuffer, sizeof (macroBuffer), macroCopy, index);
|
|
}
|
|
__except (EXCEPTION_EXECUTE_HANDLER) {
|
|
// something went wrong. The pattern might have been terribly wrong
|
|
hr = S_FALSE;
|
|
}
|
|
if (hr != S_OK) {
|
|
// something is wrong with the rename pattern. Let's just get out of here.
|
|
break;
|
|
}
|
|
newString = AllocText (
|
|
(HALF_PTR) (macroStartPtr - workingStr) +
|
|
TcharCount (macroBuffer) +
|
|
TcharCount (macroEndPtr) +
|
|
1
|
|
);
|
|
if (newString) {
|
|
StringCopyTcharCount (newString, workingStr, (HALF_PTR) (macroStartPtr - workingStr) + 1);
|
|
StringCat (newString, macroBuffer);
|
|
StringCat (newString, macroEndPtr + 1);
|
|
}
|
|
|
|
if (Leaf) {
|
|
testHandle = IsmCreateObjectHandle (Node, newString);
|
|
} else {
|
|
testHandle = IsmCreateObjectHandle (newString, NULL);
|
|
}
|
|
index++;
|
|
} while (pDoesDifferentRegExist (testHandle) ||
|
|
HtFindString (g_RegCollisionDestTable, testHandle));
|
|
|
|
if (testHandle) {
|
|
IsmDestroyObjectHandle (testHandle);
|
|
}
|
|
FreeText (macroCopy);
|
|
}
|
|
|
|
if (!newString) {
|
|
newString = DuplicateText (workingStr);
|
|
}
|
|
|
|
return newString;
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
FilterRenameExFilter (
|
|
IN PCMIG_FILTERINPUT InputData,
|
|
OUT PMIG_FILTEROUTPUT OutputData,
|
|
IN BOOL NoRestoreObject,
|
|
IN PCMIG_BLOB SourceOperationData, OPTIONAL
|
|
IN PCMIG_BLOB DestinationOperationData OPTIONAL
|
|
)
|
|
{
|
|
PCTSTR doNode = NULL;
|
|
PCTSTR doLeaf = NULL;
|
|
PCTSTR destNode = NULL;
|
|
PCTSTR newNode = NULL;
|
|
PCTSTR rootNode;
|
|
PCTSTR destLeaf = NULL;
|
|
PCTSTR srcNode = NULL;
|
|
PCTSTR srcLeaf = NULL;
|
|
// NTRAID#NTBUG9-153274-2000/08/01-jimschm Static buffer size
|
|
TCHAR newSrcNode[MAX_PATH * 4];
|
|
TCHAR newSrcLeaf[MAX_PATH * 4];
|
|
HASHITEM hashItem;
|
|
MIG_OBJECTSTRINGHANDLE storeHandle;
|
|
MIG_OBJECTSTRINGHANDLE testHandle;
|
|
MIG_OBJECTSTRINGHANDLE nodeHandle;
|
|
PTSTR ptr = NULL;
|
|
PTSTR ptr2;
|
|
PTSTR workingStr;
|
|
BOOL fFoundMatch = FALSE;
|
|
BOOL zeroBase;
|
|
|
|
|
|
IsmCreateObjectStringsFromHandle (
|
|
InputData->CurrentObject.ObjectName,
|
|
&srcNode,
|
|
&srcLeaf
|
|
);
|
|
|
|
if (srcNode) {
|
|
if (MappingSearchAndReplaceEx (
|
|
g_RegNodeFilterMap,
|
|
srcNode,
|
|
newSrcNode,
|
|
0,
|
|
NULL,
|
|
ARRAYSIZE(newSrcNode),
|
|
0,
|
|
NULL,
|
|
NULL
|
|
)) {
|
|
IsmDestroyObjectString (srcNode);
|
|
srcNode = newSrcNode;
|
|
}
|
|
}
|
|
|
|
if (srcLeaf) {
|
|
if (MappingSearchAndReplaceEx (
|
|
g_RegLeafFilterMap,
|
|
srcLeaf,
|
|
newSrcLeaf,
|
|
0,
|
|
NULL,
|
|
ARRAYSIZE(newSrcLeaf),
|
|
0,
|
|
NULL,
|
|
NULL
|
|
)) {
|
|
IsmDestroyObjectString (srcLeaf);
|
|
srcLeaf = newSrcLeaf;
|
|
}
|
|
}
|
|
|
|
if (HtFindStringEx (g_RegCollisionSrcTable, InputData->OriginalObject.ObjectName, (PVOID)(&hashItem), FALSE)) {
|
|
// We've already renamed this object
|
|
|
|
HtCopyStringData (g_RegCollisionDestTable, hashItem, (PVOID)(&testHandle));
|
|
IsmCreateObjectStringsFromHandle (testHandle, &destNode, &destLeaf);
|
|
|
|
// Do not free testHandle here because it is a pointer into the hash table data
|
|
|
|
OutputData->NewObject.ObjectName = IsmCreateObjectHandle (destNode, destLeaf);
|
|
IsmDestroyObjectString (destNode);
|
|
IsmDestroyObjectString (destLeaf);
|
|
destNode;
|
|
destLeaf = NULL;
|
|
} else {
|
|
// We've never seen this object yet
|
|
|
|
IsmCreateObjectStringsFromHandle (DestinationOperationData->String, &doNode, &doLeaf);
|
|
|
|
// Pick a new node
|
|
|
|
// First check to see if this object's node has already been processed
|
|
workingStr = DuplicateText(srcNode);
|
|
if (workingStr) {
|
|
do {
|
|
nodeHandle = IsmCreateObjectHandle (workingStr, NULL);
|
|
if (HtFindStringEx (g_RegCollisionSrcTable, nodeHandle, (PVOID)(&hashItem), FALSE)) {
|
|
|
|
HtCopyStringData (g_RegCollisionDestTable, hashItem, (PVOID)(&testHandle));
|
|
IsmCreateObjectStringsFromHandle (testHandle, &rootNode, NULL);
|
|
// Do not free testHandle here because it is a pointer into the hash table data
|
|
|
|
if (ptr) {
|
|
// if ptr is valid it means we found a match for a subkey
|
|
*ptr = TEXT('\\');
|
|
newNode = JoinText(rootNode, ptr);
|
|
} else {
|
|
// if ptr is NULL, we found a match for the full keyname
|
|
newNode = DuplicateText(rootNode);
|
|
}
|
|
IsmDestroyObjectString(rootNode);
|
|
fFoundMatch = TRUE;
|
|
} else {
|
|
ptr2 = ptr;
|
|
ptr = (PTSTR)FindLastWack (workingStr);
|
|
if (ptr2) {
|
|
*ptr2 = TEXT('\\');
|
|
}
|
|
if (ptr) {
|
|
*ptr = 0;
|
|
}
|
|
}
|
|
IsmDestroyObjectHandle(nodeHandle);
|
|
} while (FALSE == fFoundMatch && ptr);
|
|
FreeText(workingStr);
|
|
}
|
|
|
|
zeroBase = (SourceOperationData &&
|
|
SourceOperationData->Type == BLOBTYPE_BINARY &&
|
|
SourceOperationData->BinarySize == sizeof(PCBYTE) &&
|
|
(BOOL)SourceOperationData->BinaryData == TRUE);
|
|
|
|
if (FALSE == fFoundMatch) {
|
|
// Nope, let's process the node
|
|
destNode = pProcessRenameExMacro (doNode, NULL, zeroBase);
|
|
newNode = DuplicateText(destNode);
|
|
IsmDestroyObjectHandle(destNode);
|
|
}
|
|
|
|
// Now process the leaf, if the original object had a leaf
|
|
if (srcLeaf) {
|
|
if (doLeaf) {
|
|
destLeaf = pProcessRenameExMacro (newNode, doLeaf, zeroBase);
|
|
IsmDestroyObjectString (doLeaf);
|
|
}
|
|
}
|
|
IsmDestroyObjectString (doNode);
|
|
|
|
// Add this in the collision table
|
|
testHandle = IsmCreateObjectHandle (newNode, destLeaf ? destLeaf : srcLeaf);
|
|
storeHandle = DuplicateText (testHandle);
|
|
hashItem = HtAddStringEx (g_RegCollisionDestTable, storeHandle, &storeHandle, FALSE);
|
|
HtAddStringEx (g_RegCollisionSrcTable, InputData->OriginalObject.ObjectName, &hashItem, FALSE);
|
|
|
|
// Update the output
|
|
OutputData->NewObject.ObjectName = testHandle;
|
|
}
|
|
|
|
if (srcNode != NULL) {
|
|
IsmDestroyObjectString (srcNode);
|
|
}
|
|
if (srcLeaf != NULL) {
|
|
IsmDestroyObjectString (srcLeaf);
|
|
}
|
|
if (destLeaf != NULL) {
|
|
IsmDestroyObjectString (destLeaf);
|
|
}
|
|
if (newNode != NULL) {
|
|
FreeText(newNode);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
FilterRenameIniExFilter (
|
|
IN PCMIG_FILTERINPUT InputData,
|
|
OUT PMIG_FILTEROUTPUT OutputData,
|
|
IN BOOL NoRestoreObject,
|
|
IN PCMIG_BLOB SourceOperationData, OPTIONAL
|
|
IN PCMIG_BLOB DestinationOperationData OPTIONAL
|
|
)
|
|
{
|
|
// we should never get here since there is no INF rule
|
|
// that would trigger this filter
|
|
|
|
MYASSERT(FALSE);
|
|
|
|
// As we said, we should never get here. If we do however, we
|
|
// will just continue
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
FilterPartitionMove (
|
|
IN PCMIG_FILTERINPUT InputData,
|
|
OUT PMIG_FILTEROUTPUT OutputData,
|
|
IN BOOL NoRestoreObject,
|
|
IN PCMIG_BLOB SourceOperationData, OPTIONAL
|
|
IN PCMIG_BLOB DestinationOperationData OPTIONAL
|
|
)
|
|
{
|
|
PCTSTR node = NULL;
|
|
PCTSTR leaf = NULL;
|
|
|
|
IsmCreateObjectStringsFromHandle (DestinationOperationData->String, &node, &leaf);
|
|
|
|
OutputData->NewObject.ObjectName = IsmCreateObjectHandle (node, leaf);
|
|
|
|
IsmDestroyObjectString (node);
|
|
IsmDestroyObjectString (leaf);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
DoDestAddObject (
|
|
IN MIG_OBJECTTYPEID SrcObjectTypeId,
|
|
IN MIG_OBJECTSTRINGHANDLE SrcObjectName,
|
|
IN PCMIG_CONTENT OriginalContent,
|
|
IN PCMIG_CONTENT CurrentContent,
|
|
OUT PMIG_CONTENT NewContent,
|
|
IN PCMIG_BLOB SourceOperationData, OPTIONAL
|
|
IN PCMIG_BLOB DestinationOperationData OPTIONAL
|
|
)
|
|
{
|
|
PMIG_CONTENT finalContent;
|
|
|
|
if (DestinationOperationData == NULL) {
|
|
return TRUE;
|
|
}
|
|
if (DestinationOperationData->Type != BLOBTYPE_BINARY) {
|
|
return TRUE;
|
|
}
|
|
if (DestinationOperationData->BinarySize != sizeof (MIG_CONTENT)) {
|
|
return TRUE;
|
|
}
|
|
|
|
finalContent = (PMIG_CONTENT) DestinationOperationData->BinaryData;
|
|
CopyMemory (NewContent, finalContent, sizeof (MIG_CONTENT));
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
VOID
|
|
OEWarning (
|
|
VOID
|
|
)
|
|
{
|
|
ERRUSER_EXTRADATA extraData;
|
|
|
|
if (TRUE == g_OERulesMigrated) {
|
|
// Send warning to app
|
|
extraData.Error = ERRUSER_WARNING_OERULES;
|
|
extraData.ErrorArea = ERRUSER_AREA_RESTORE;
|
|
extraData.ObjectTypeId = 0;
|
|
extraData.ObjectName = NULL;
|
|
IsmSendMessageToApp (MODULEMESSAGE_DISPLAYERROR, (ULONG_PTR)(&extraData));
|
|
|
|
// Add to log
|
|
LOG ((LOG_WARNING, (PCSTR) MSG_OE_RULES));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
OutlookWarning (
|
|
VOID
|
|
)
|
|
{
|
|
PCTSTR expandedPath;
|
|
MIG_OBJECT_ENUM objectEnum;
|
|
PCTSTR enumPattern;
|
|
ERRUSER_EXTRADATA extraData;
|
|
|
|
expandedPath = IsmExpandEnvironmentString (PLATFORM_SOURCE,
|
|
S_SYSENVVAR_GROUP,
|
|
TEXT("%CSIDL_APPDATA%\\Microsoft\\Outlook"),
|
|
NULL);
|
|
if (expandedPath) {
|
|
enumPattern = IsmCreateSimpleObjectPattern (expandedPath, FALSE, TEXT("*.rwz"), TRUE);
|
|
if (enumPattern) {
|
|
if (IsmEnumFirstSourceObject (&objectEnum, g_FileType, enumPattern)) {
|
|
// Send warning to app
|
|
extraData.Error = ERRUSER_WARNING_OUTLOOKRULES;
|
|
extraData.ErrorArea = ERRUSER_AREA_RESTORE;
|
|
extraData.ObjectTypeId = 0;
|
|
extraData.ObjectName = NULL;
|
|
IsmSendMessageToApp (MODULEMESSAGE_DISPLAYERROR, (ULONG_PTR)(&extraData));
|
|
|
|
// Add to log
|
|
LOG ((LOG_WARNING, (PCSTR) MSG_OUTLOOK_RULES));
|
|
|
|
IsmAbortObjectEnum (&objectEnum);
|
|
}
|
|
IsmDestroyObjectHandle (enumPattern);
|
|
}
|
|
IsmReleaseMemory (expandedPath);
|
|
}
|
|
|
|
}
|
|
|
|
VOID
|
|
WINAPI
|
|
ScriptOpmTerminate (
|
|
VOID
|
|
)
|
|
{
|
|
//
|
|
// Temporary place to trigger setting refresh/upgrade
|
|
//
|
|
|
|
if (!IsmCheckCancel()) {
|
|
OEFixLastUser();
|
|
WABMerge();
|
|
OE4MergeStoreFolder();
|
|
OE5MergeStoreFolders();
|
|
OEWarning();
|
|
OutlookWarning();
|
|
}
|
|
|
|
TerminateRestoreCallback ();
|
|
TerminateSpecialRename();
|
|
TerminateSpecialConversion();
|
|
|
|
// LEAK: need to loop through table and FreeText the extra data
|
|
HtFree (g_RegCollisionDestTable);
|
|
g_RegCollisionDestTable = NULL;
|
|
|
|
HtFree (g_RegCollisionSrcTable);
|
|
g_RegCollisionSrcTable = NULL;
|
|
|
|
DestroyStringMapping (g_RegNodeFilterMap);
|
|
g_RegNodeFilterMap = NULL;
|
|
|
|
DestroyStringMapping (g_RegLeafFilterMap);
|
|
g_RegLeafFilterMap = NULL;
|
|
|
|
DestroyStringMapping (g_FileNodeFilterMap);
|
|
g_FileNodeFilterMap = NULL;
|
|
|
|
DestroyStringMapping (g_FileLeafFilterMap);
|
|
g_FileLeafFilterMap = NULL;
|
|
|
|
DestroyStringMapping (g_IniSectFilterMap);
|
|
g_IniSectFilterMap = NULL;
|
|
|
|
DestroyStringMapping (g_IniKeyFilterMap);
|
|
g_IniKeyFilterMap = NULL;
|
|
|
|
DestroyStringMapping (g_DestEnvMap);
|
|
g_DestEnvMap = NULL;
|
|
}
|
|
|
|
|