Leaked source code of windows server 2003
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.
 
 
 
 
 
 

575 lines
15 KiB

/*++
Copyright (c) 1999 Microsoft Corporation
Module Name:
restore.c
Abstract:
Implements object restore callbacks
Author:
Calin Negreanu (calinn) 21-Nov-2000
Revision History:
<alias> <date> <comments>
--*/
//
// Includes
//
#include "pch.h"
#include "v1p.h"
#define DBG_RESTORE "RestoreCallbacks"
//
// Strings
//
// None
//
// Constants
//
// None
//
// Macros
//
// None
//
// Types
//
typedef BOOL(WINAPI SCRIPTRESTOREFUNCTION)(
IN MIG_OBJECTTYPEID ObjectTypeId,
IN MIG_OBJECTID ObjectId,
IN MIG_OBJECTSTRINGHANDLE ObjectName,
IN PCTSTR MultiSzData
);
typedef SCRIPTRESTOREFUNCTION *PSCRIPTRESTOREFUNCTION;
//
// This is the structure used for handling restore callback functions
//
typedef struct {
PCTSTR InfFunctionName;
PSCRIPTRESTOREFUNCTION RestoreCallback;
} RESTORE_STRUCT, *PRESTORE_STRUCT;
typedef struct _RESTOREDATA_STRUCT{
POBSPARSEDPATTERN ParsedPattern;
PCTSTR RestoreArgs;
PRESTORE_STRUCT RestoreStruct;
struct _RESTOREDATA_STRUCT *Next;
} RESTOREDATA_STRUCT, *PRESTOREDATA_STRUCT;
//
// Globals
//
PRESTOREDATA_STRUCT g_RestoreData = NULL;
PMHANDLE g_RestorePool;
//
// Macro expansion list
//
#define RESTORE_FUNCTIONS \
DEFMAC(NEVER, pNever ) \
DEFMAC(SAMEREGVALUE, pSameRegValue ) \
DEFMAC(EXISTSINHKLM, pExistsInHKLM ) \
//
// Private function prototypes
//
MIG_RESTORECALLBACK pRestoreCallback;
//
// Macro expansion definition
//
//
// Declare special conversion operation apply callback functions
//
#define DEFMAC(ifn,fn) SCRIPTRESTOREFUNCTION fn;
RESTORE_FUNCTIONS
#undef DEFMAC
//
// Declare a global array of conversion functions
//
#define DEFMAC(ifn,fn) {TEXT("\\")TEXT(#ifn),fn},
static RESTORE_STRUCT g_RestoreFunctions[] = {
RESTORE_FUNCTIONS
{NULL, NULL}
};
#undef DEFMAC
//
// Code
//
PRESTORE_STRUCT
pGetRestoreStruct (
IN PCTSTR FunctionName
)
{
PRESTORE_STRUCT p = g_RestoreFunctions;
INT i = 0;
while (p->InfFunctionName != NULL) {
if (StringIMatch (p->InfFunctionName, FunctionName)) {
return p;
}
p++;
i++;
}
return NULL;
}
BOOL
pParseRestoreInf (
IN HINF InfHandle
)
{
INFSTRUCT is = INITINFSTRUCT_PMHANDLE;
PCTSTR pattern;
PCTSTR fnName;
PCTSTR fnArgs;
ENCODEDSTRHANDLE srcHandle = NULL;
BOOL result = FALSE;
GROWBUFFER multiSz = INIT_GROWBUFFER;
MULTISZ_ENUM e;
UINT sizeNeeded;
PRESTOREDATA_STRUCT restoreData;
__try {
if (!IsmGetEnvironmentMultiSz (
PLATFORM_SOURCE,
NULL,
S_ENV_DEST_RESTORE,
NULL,
0,
&sizeNeeded
)) {
result = TRUE;
__leave;
}
if (!GbGrow (&multiSz, sizeNeeded)) {
__leave;
}
if (!IsmGetEnvironmentMultiSz (
PLATFORM_SOURCE,
NULL,
S_ENV_DEST_RESTORE,
(PTSTR) multiSz.Buf,
multiSz.End,
NULL
)) {
__leave;
}
if (EnumFirstMultiSz (&e, (PCTSTR) multiSz.Buf)) {
do {
if (InfFindFirstLine (InfHandle, e.CurrentString, NULL, &is)) {
do {
if (IsmCheckCancel()) {
__leave;
}
pattern = InfGetStringField (&is, 0);
if (!pattern) {
LOG ((LOG_WARNING, (PCSTR) MSG_EMPTY_REG_SPEC));
continue;
}
srcHandle = TurnRegStringIntoHandle (pattern, TRUE, NULL);
if (!srcHandle) {
LOG ((LOG_ERROR, (PCSTR) MSG_REG_SPEC_BAD, pattern));
continue;
}
fnName = InfGetStringField (&is, 1);
if (!fnName) {
LOG ((LOG_ERROR, (PCSTR) MSG_REG_SPEC_BAD, pattern));
IsmDestroyObjectHandle (srcHandle);
srcHandle = NULL;
continue;
}
fnArgs = InfGetMultiSzField (&is, 2);
restoreData = PmGetMemory (g_RestorePool, sizeof (RESTOREDATA_STRUCT));
ZeroMemory (restoreData, sizeof (RESTOREDATA_STRUCT));
restoreData->ParsedPattern = ObsCreateParsedPatternEx (g_RestorePool, srcHandle, FALSE);
if (fnArgs) {
restoreData->RestoreArgs = PmDuplicateMultiSz (g_RestorePool, fnArgs);
}
if (fnName) {
restoreData->RestoreStruct = pGetRestoreStruct (fnName);
}
restoreData->Next = g_RestoreData;
g_RestoreData = restoreData;
IsmDestroyObjectHandle (srcHandle);
srcHandle = NULL;
} while (InfFindNextLine (&is));
}
} while (EnumNextMultiSz (&e));
}
result = TRUE;
}
__finally {
GbFree (&multiSz);
InfCleanUpInfStruct (&is);
}
return result;
}
BOOL
InitRestoreCallback (
IN MIG_PLATFORMTYPEID Platform
)
{
PTSTR multiSz = NULL;
MULTISZ_ENUM e;
UINT sizeNeeded;
HINF infHandle = INVALID_HANDLE_VALUE;
ENVENTRY_TYPE dataType;
BOOL result = FALSE;
g_RestorePool = PmCreateNamedPoolEx ("Restore Callback Data", 32768);
PmDisableTracking (g_RestorePool);
if (IsmGetEnvironmentValue (
IsmGetRealPlatform (),
NULL,
S_GLOBAL_INF_HANDLE,
(PBYTE)(&infHandle),
sizeof (HINF),
&sizeNeeded,
&dataType
) &&
(sizeNeeded == sizeof (HINF)) &&
(dataType == ENVENTRY_BINARY)
) {
if (pParseRestoreInf (infHandle)) {
result = TRUE;
}
InfNameHandle (infHandle, NULL, 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) {
__leave;
}
if (!IsmGetEnvironmentValue (IsmGetRealPlatform (), NULL, S_INF_FILE_MULTISZ, (PBYTE) multiSz, sizeNeeded, NULL, NULL)) {
__leave;
}
if (EnumFirstMultiSz (&e, multiSz)) {
do {
infHandle = InfOpenInfFile (e.CurrentString);
if (infHandle != INVALID_HANDLE_VALUE) {
if (!pParseRestoreInf (infHandle)) {
InfCloseInfFile (infHandle);
infHandle = INVALID_HANDLE_VALUE;
__leave;
}
} else {
LOG ((LOG_ERROR, (PCSTR) MSG_CANT_OPEN_INF, e.CurrentString));
}
InfCloseInfFile (infHandle);
infHandle = INVALID_HANDLE_VALUE;
} while (EnumNextMultiSz (&e));
}
result = TRUE;
}
__finally {
if (multiSz) {
FreeText (multiSz);
multiSz = NULL;
}
}
}
IsmRegisterRestoreCallback (pRestoreCallback);
return result;
}
VOID
TerminateRestoreCallback (
VOID
)
{
if (g_RestorePool) {
PmEmptyPool (g_RestorePool);
PmDestroyPool (g_RestorePool);
g_RestorePool = NULL;
}
}
BOOL
pRestoreCallback (
IN MIG_OBJECTTYPEID ObjectTypeId,
IN MIG_OBJECTID ObjectId,
IN MIG_OBJECTSTRINGHANDLE ObjectName
)
{
BOOL result = TRUE;
PRESTOREDATA_STRUCT p = g_RestoreData;
if (ObjectTypeId & MIG_REGISTRY_TYPE) {
while (p) {
if (p->ParsedPattern) {
if (IsmParsedPatternMatch ((MIG_PARSEDPATTERN)p->ParsedPattern, MIG_REGISTRY_TYPE, ObjectName)) {
if (p->RestoreStruct) {
if (p->RestoreStruct->RestoreCallback) {
if (!p->RestoreStruct->RestoreCallback (
ObjectTypeId,
ObjectId,
ObjectName,
p->RestoreArgs
)) {
result = FALSE;
break;
}
}
}
}
}
p = p->Next;
}
}
return result;
}
BOOL
pIsSameContent (
IN PMIG_CONTENT ContentSrc,
IN PMIG_CONTENT ContentDest
)
{
INT value1 = 0;
INT value2 = 0;
if (ContentSrc->ContentInFile) {
return FALSE;
}
if (ContentDest->ContentInFile) {
return FALSE;
}
if (ContentSrc->Details.DetailsSize != ContentDest->Details.DetailsSize) {
return FALSE;
}
if (!TestBuffer (
ContentSrc->Details.DetailsData,
ContentDest->Details.DetailsData,
ContentSrc->Details.DetailsSize
)) {
return FALSE;
}
if ((ContentSrc->MemoryContent.ContentSize == 0) &&
(ContentDest->MemoryContent.ContentSize == 0)
) {
// no content, just return TRUE
return TRUE;
}
if ((ContentSrc->MemoryContent.ContentSize == ContentDest->MemoryContent.ContentSize) &&
TestBuffer (
ContentSrc->MemoryContent.ContentBytes,
ContentDest->MemoryContent.ContentBytes,
ContentSrc->MemoryContent.ContentSize
)) {
// same exact content
return TRUE;
}
// we have an extra case, if the source and dest are strings but they are actually numbers
// we will get the numbers and compare them
if ((ContentSrc->Details.DetailsSize == sizeof (DWORD)) &&
(ContentSrc->Details.DetailsData) &&
(ContentDest->Details.DetailsData) &&
((*(PDWORD)ContentSrc->Details.DetailsData == REG_SZ) ||
(*(PDWORD)ContentSrc->Details.DetailsData == REG_EXPAND_SZ)
) &&
((*(PDWORD)ContentDest->Details.DetailsData == REG_SZ) ||
(*(PDWORD)ContentDest->Details.DetailsData == REG_EXPAND_SZ)
) &&
(ContentSrc->MemoryContent.ContentBytes) &&
(ContentDest->MemoryContent.ContentBytes)
) {
value1 = _ttoi ((PCTSTR)ContentSrc->MemoryContent.ContentBytes);
value2 = _ttoi ((PCTSTR)ContentDest->MemoryContent.ContentBytes);
if ((value1 != 0) &&
(value2 != 0) &&
(value1 == value2)
) {
return TRUE;
}
}
return FALSE;
}
BOOL
pSameRegValue (
IN MIG_OBJECTTYPEID ObjectTypeId,
IN MIG_OBJECTID ObjectId,
IN MIG_OBJECTSTRINGHANDLE ObjectName,
IN PCTSTR MultiSzData
)
{
MIG_OBJECTSTRINGHANDLE objectName;
BOOL hadLeaf = FALSE;
BOOL existsSrc = FALSE;
MIG_CONTENT contentSrc;
BOOL existsDest = FALSE;
MIG_CONTENT contentDest;
BOOL result = TRUE;
if (MultiSzData) {
objectName = TurnRegStringIntoHandle (MultiSzData, FALSE, &hadLeaf);
if (objectName) {
existsSrc = IsmAcquireObjectEx (
MIG_REGISTRY_TYPE | PLATFORM_SOURCE,
objectName,
&contentSrc,
CONTENTTYPE_MEMORY,
0
);
existsDest = IsmAcquireObjectEx (
MIG_REGISTRY_TYPE | PLATFORM_DESTINATION,
objectName,
&contentDest,
CONTENTTYPE_MEMORY,
0
);
result = (existsSrc && existsDest) || (!existsSrc && !existsDest);
if (hadLeaf && result && existsSrc && existsDest) {
result = pIsSameContent (&contentSrc, &contentDest);
}
if (existsSrc) {
IsmReleaseObject (&contentSrc);
}
if (existsDest) {
IsmReleaseObject (&contentDest);
}
}
}
return result;
}
BOOL
pNever (
IN MIG_OBJECTTYPEID ObjectTypeId,
IN MIG_OBJECTID ObjectId,
IN MIG_OBJECTSTRINGHANDLE ObjectName,
IN PCTSTR MultiSzData
)
{
return FALSE;
}
BOOL
pExistsInHKLM (
IN MIG_OBJECTTYPEID ObjectTypeId,
IN MIG_OBJECTID ObjectId,
IN MIG_OBJECTSTRINGHANDLE ObjectName,
IN PCTSTR MultiSzData
)
{
MIG_OBJECTSTRINGHANDLE newObjectName;
PCTSTR node, leaf, nodePtr, newNode;
MIG_CONTENT content;
BOOL result = TRUE;
if (ObjectTypeId == (MIG_REGISTRY_TYPE | PLATFORM_SOURCE)) {
if (IsmCreateObjectStringsFromHandle (ObjectName, &node, &leaf)) {
if (node && StringIPrefix (node, TEXT("HKCU\\"))) {
nodePtr = node + ARRAYSIZE (TEXT("HKCU"));
newNode = JoinPathsInPoolEx ((
NULL,
TEXT("HKLM"),
MultiSzData?MultiSzData:nodePtr,
MultiSzData?nodePtr:NULL,
NULL
));
newObjectName = IsmCreateObjectHandle (newNode, leaf);
if (newObjectName) {
result = !IsmAcquireObjectEx (
MIG_REGISTRY_TYPE | PLATFORM_DESTINATION,
newObjectName,
&content,
CONTENTTYPE_MEMORY,
0
);
if (!result) {
IsmReleaseObject (&content);
}
IsmDestroyObjectHandle (newObjectName);
}
FreePathString (newNode);
}
IsmDestroyObjectString (node);
IsmDestroyObjectString (leaf);
}
}
return result;
}