windows-nt/Source/XPSP1/NT/base/ntsetup/win95upg/w95upgnt/merge/merge.c
2020-09-26 16:20:57 +08:00

2112 lines
52 KiB
C

/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
merge.c
Abstract:
Registry merge code
Author:
Jim Schmidt (jimschm) 17-Feb-1997
Revision History:
jimschm 23-Sep-1998 String mapping mechanism
jimschm 24-Mar-1998 Added more complex hkcr processing
--*/
#include "pch.h"
#include "mergep.h"
static PCTSTR g_InfFileName;
BOOL g_ProcessRenameTable = FALSE;
DWORD g_ProgressBarCounter;
HKEY g_DuHandle;
BOOL
pForceCopy (
HINF InfFile
);
BOOL
pForceCopyFromMemDb (
VOID
);
BOOL
pCreateRenameTable (
IN HINF InfFile,
OUT PVOID *RenameTablePtr
);
BOOL
pProcessRenameTable (
IN PVOID RenameTable
);
BOOL
pSpecialConversion (
IN HINF InfFile,
IN PCTSTR User,
IN PVOID RenameTable
);
BOOL
pProcessSuppressList (
IN HINF InfFile,
IN PCTSTR SectionName
);
BOOL
pProcessHardwareSuppressList (
IN HINF InfFile
);
BOOL
pSuppressNTDefaults (
IN HINF InfFile,
IN PCTSTR SectionName
);
BOOL
pDontCombineWithDefaults (
IN HINF InfFile,
IN PCTSTR SectionName
);
BOOL
pForceNTDefaults (
IN HINF InfFile,
IN PCTSTR SectionName
);
BOOL
pForceNTDefaultsHack (
IN HINF InfFile,
IN PCTSTR SectionName
);
BOOL
pMergeWin95WithUser (
IN PVOID RenameTable
);
BOOL
pSpecialConversionNT (
IN HINF InfFile,
IN PCTSTR User,
IN BOOL PerUser
);
BOOL
pMergeNTDefaultsWithUser (
IN HINF InfFile
);
BOOL
pCopyWin95ToSystem (
VOID
);
BOOL
pMergeWin95WithSystem (
VOID
);
BOOL
pDeleteAfterMigration (
IN HINF InfFile
);
FILTERRETURN
SuppressFilter95 (
IN CPDATAOBJECT SrcObjectPtr,
IN CPDATAOBJECT DestObjectPtr, OPTIONAL
IN FILTERTYPE FilterType,
IN PVOID DontCare
);
//
// Globals
//
POOLHANDLE g_TempPool;
POOLHANDLE g_RenamePool;
PMAPSTRUCT g_CompleteMatchMap;
PMAPSTRUCT g_SubStringMap;
BOOL
WINAPI
Merge_Entry (
IN HINSTANCE hinstDLL,
IN DWORD dwReason,
IN PVOID lpv
)
/*++
Routine Description:
DllMain is called after the C runtime is initialized, and its purpose
is to initialize the globals for this process.
Arguments:
hinstDLL - (OS-supplied) Instance handle for the DLL
dwReason - (OS-supplied) Type of initialization or termination
lpv - (OS-supplied) Unused
Return Value:
TRUE because DLL always initializes properly.
--*/
{
switch (dwReason)
{
case DLL_PROCESS_ATTACH:
if(!pSetupInitializeUtils()) {
return FALSE;
}
g_CompleteMatchMap = CreateStringMapping();
g_SubStringMap = CreateStringMapping();
break;
case DLL_PROCESS_DETACH:
DestroyStringMapping (g_CompleteMatchMap);
DestroyStringMapping (g_SubStringMap);
pSetupUninitializeUtils();
break;
}
return TRUE;
}
BOOL
MergeRegistry (
IN PCTSTR FileName,
IN PCTSTR User
)
{
HINF hInf; // handle to the INF being processed
BOOL b = FALSE; // Return value
PVOID RenameTable = NULL;
BOOL LogonAccount = FALSE;
BOOL DefaultUserAccount = FALSE;
g_ProgressBarCounter = 0;
//
// Open the INF
//
g_InfFileName = FileName;
hInf = InfOpenInfFile (FileName);
if (hInf == INVALID_HANDLE_VALUE) {
LOG ((LOG_ERROR, "MergeRegistry: SetupOpenInfFile failed for %s", FileName));
return FALSE;
}
g_TempPool = PoolMemInitNamedPool ("Merge: temp pool");
g_RenamePool = PoolMemInitNamedPool ("Merge: Rename pool");
if (!g_TempPool || !g_RenamePool) {
DEBUGMSG ((DBG_ERROR, "MergeRegistry: Can't init pool"));
goto c0;
}
PoolMemSetMinimumGrowthSize (g_TempPool, 16384);
if (User) {
SetCurrentUserW (g_FixedUserName);
}
//
// Perform forced copy of Win95 registry, build rename table,
// execute registry value conversions, convert types, and mark
// specified keys as suppressed.
//
if (!pForceCopy (hInf)) {
goto c0;
}
if (!User) {
if (!pForceCopyFromMemDb ()) {
goto c0;
}
}
if (!pCreateRenameTable (hInf, &RenameTable)) {
goto c0;
}
//
// Identify the logon account or default user account
//
if (User) {
if (*User == 0 || StringIMatch (User, S_DOT_DEFAULT)) {
DEBUGMSG ((DBG_NAUSEA, "The logon user account is indicated by user name '%s'", User));
LogonAccount = TRUE;
} else if (StringIMatch (User, S_DEFAULT_USER)) {
DEBUGMSG ((DBG_NAUSEA, "The default user account template is indicated by user name '%s'", User));
DefaultUserAccount = TRUE;
}
}
//
// Prepare flags for registry merging
//
if (!pProcessSuppressList (hInf, S_MERGE_WIN9X_SUPPRESS)) {
goto c0;
}
if (User) {
//
// These functions read usermig.inf and set flags
// for the keys, key trees or values, as specified in
// the INF.
//
if (!pSuppressNTDefaults (hInf, S_MERGE_WINNT_SUPPRESS)) {
goto c0;
}
if (!pDontCombineWithDefaults (hInf, S_MERGE_DONT_COMBINE_WITH_DEFAULT)) {
goto c0;
}
if (!pForceNTDefaults (hInf, S_MERGE_FORCE_NT_DEFAULTS)) {
goto c0;
}
if (LogonAccount) {
if (!pProcessSuppressList (hInf, S_MERGE_WIN9X_SUPPRESS_LU)) {
goto c0;
}
}
if (DefaultUserAccount) {
if (!pProcessSuppressList (hInf, S_MERGE_WIN9X_SUPPRESS_DU)) {
goto c0;
}
}
g_DuHandle = OpenRegKeyStr (L"hklm\\" S_MAPPED_DEFAULT_USER_KEY);
} else {
if (!pForceNTDefaults (hInf, S_MERGE_FORCE_NT_DEFAULTS)) {
goto c0;
}
if (!pProcessHardwareSuppressList (hInf)) {
goto c0;
}
}
if (!pSpecialConversion (hInf, User, RenameTable)) {
goto c0;
}
//
// Perform merge
//
if (User) {
// User merge
if (!pMergeWin95WithUser (RenameTable)) {
goto c0;
}
if (!pSpecialConversionNT (hInf, User, TRUE)) {
goto c0;
}
if (!LogonAccount && !DefaultUserAccount) {
// Non-default user, not logon prompt account
if (!pMergeNTDefaultsWithUser (hInf)) {
goto c0;
}
}
}
else {
// Workstation merge
if (!pCopyWin95ToSystem()) {
goto c0;
}
if (!pForceNTDefaultsHack (hInf, S_MERGE_FORCE_NT_DEFAULTS)) {
goto c0;
}
if (!pMergeWin95WithSystem()) {
goto c0;
}
if (!CopyHardwareProfiles (hInf)) {
goto c0;
}
TickProgressBar ();
if (!pSpecialConversionNT (hInf, NULL, FALSE)) {
goto c0;
}
TickProgressBar ();
}
g_ProcessRenameTable = TRUE;
b = pProcessRenameTable (RenameTable);
TickProgressBar ();
g_ProcessRenameTable = FALSE;
//
// Once we are done with the complete registry merge, process the special section
// [Delete After Migration]
//
if (!pDeleteAfterMigration (hInf)) {
LOG((LOG_ERROR,"Registry Merge: Delete After Migration failed."));
goto c0;
}
c0:
if (RenameTable) {
pSetupStringTableDestroy (RenameTable);
}
if (User) {
SetCurrentUserW (NULL);
}
if (g_TempPool) {
PoolMemDestroyPool (g_TempPool);
}
if (g_RenamePool) {
PoolMemDestroyPool (g_RenamePool);
}
if (g_DuHandle) {
CloseRegKey (g_DuHandle);
g_DuHandle = NULL;
}
InfCloseInfFile (hInf);
return b;
}
PTSTR
pGetStringFromObjectData (
IN CPDATAOBJECT ObPtr
)
{
PTSTR p;
PTSTR end;
//
// Value type has to be a registry object
//
if (!DoesObjectHaveValue (ObPtr) ||
!IsRegistryTypeSpecified (ObPtr)
) {
return NULL;
}
if (ObPtr->Type == REG_DWORD) {
return NULL;
}
if (ObPtr->Value.Size & 1) {
return NULL;
}
p = (PTSTR) ObPtr->Value.Buffer;
end = (PTSTR) ((PBYTE) p + ObPtr->Value.Size);
if ((end - p) >= MAX_PATH) {
return NULL;
}
if (ObPtr->Type == REG_SZ || ObPtr->Type == REG_EXPAND_SZ) {
return p;
}
//
// For REG_NONE and REG_BINARY, give it a try by looking for a terminated string
//
if (*(end - 1)) {
return NULL;
}
return p;
}
BOOL
SetObjectStringFlag (
IN PCTSTR ObjectStr,
IN DWORD Flag,
IN DWORD RemoveFlag
)
{
DWORD Val;
if (!MemDbGetValue (ObjectStr, &Val)) {
Val = 0;
}
if (Val & RemoveFlag) {
if (Val & RemoveFlag & (~Flag)) {
DEBUGMSG ((DBG_WARNING, "SetObjectStringFlag: Removing flag %x from val %x in %s",
Val & RemoveFlag, Val, ObjectStr));
Val = Val & (~RemoveFlag);
}
}
Val |= Flag;
return MemDbSetValue (ObjectStr, Val);
}
BOOL
SetObjectStructFlag (
IN CPDATAOBJECT ObPtr,
DWORD Flag,
DWORD RemoveFlag
)
{
TCHAR EncodedObject[MAX_ENCODED_RULE];
CreateObjectString (ObPtr, EncodedObject);
return SetObjectStringFlag (EncodedObject, Flag, RemoveFlag);
}
BOOL
CreateRenamedObjectStruct (
IN PVOID RenameTable,
IN PDATAOBJECT InObPtr,
OUT PDATAOBJECT OutObPtr
)
// returns TRUE when OutObPtr is different than InObPtr
{
LONG rc;
PCTSTR NewPtr;
PTSTR p;
PCTSTR Tail;
PCTSTR RealValueName;
TCHAR EncodedObject[MAX_ENCODED_RULE];
TCHAR CopyOfEncodedObject[MAX_ENCODED_RULE];
PTSTR NewEncodedObject;
BOOL b = FALSE;
ZeroMemory (OutObPtr, sizeof (DATAOBJECT));
if (InObPtr->KeyPtr) {
// Look for HKR\sub\key
InObPtr->ObjectType &= ~(OT_TREE);
RealValueName = InObPtr->ValueName;
InObPtr->ValueName = NULL;
CreateObjectString (InObPtr, EncodedObject);
StringCopy (CopyOfEncodedObject, EncodedObject);
InObPtr->ValueName = RealValueName;
rc = pSetupStringTableLookUpStringEx (RenameTable,
EncodedObject,
STRTAB_CASE_INSENSITIVE,
(PBYTE) &NewPtr,
sizeof (NewPtr)
);
if (rc != -1) {
CreateObjectStruct (NewPtr, OutObPtr, WINNTOBJECT);
b = TRUE;
} else if (*EncodedObject) {
// Look for HKR\sub\key\*, HKR\sub\* and HKR\*
p = GetEndOfString (EncodedObject);
do {
StringCopy (p, TEXT("\\*"));
rc = pSetupStringTableLookUpStringEx (RenameTable,
EncodedObject,
STRTAB_CASE_INSENSITIVE,
(PBYTE) &NewPtr,
sizeof (NewPtr)
);
if (rc != -1) {
Tail = CopyOfEncodedObject + (p - EncodedObject);
NewEncodedObject = JoinPaths (NewPtr, Tail);
CreateObjectStruct (NewEncodedObject, OutObPtr, WINNTOBJECT);
FreePathString (NewEncodedObject);
b = TRUE;
break;
}
do {
// _tcsdec is fixed in strings.h
p = _tcsdec2 (EncodedObject, p);
} while (p && _tcsnextc (p) != TEXT('\\'));
} while (p);
}
}
if (InObPtr->ValueName) {
if (InObPtr->KeyPtr) {
// Look for HKR\sub\key\[value]
CreateObjectString (InObPtr, EncodedObject);
rc = pSetupStringTableLookUpStringEx (RenameTable,
EncodedObject,
STRTAB_CASE_INSENSITIVE,
(PBYTE) &NewPtr,
sizeof (NewPtr)
);
if (rc != -1) {
CreateObjectStruct (NewPtr, OutObPtr, WINNTOBJECT);
b = TRUE;
}
}
}
if (!b) {
// If rename not found, copy in object to out object
CopyMemory (OutObPtr, InObPtr, sizeof (DATAOBJECT));
}
return b;
}
BOOL
CreateRenamedObjectString (
IN PVOID RenameTable,
IN PCTSTR InObStr,
OUT PTSTR OutObStr
)
{
DATAOBJECT InObject, OutObject;
BOOL b;
if (!CreateObjectStruct (InObStr, &InObject, WIN95OBJECT)) {
return FALSE;
}
b = CreateRenamedObjectStruct (RenameTable, &InObject, &OutObject);
CreateObjectString (&OutObject, OutObStr);
FreeObjectStruct (&InObject);
if (b) {
FreeObjectStruct (&OutObject);
}
return b;
}
BOOL
pForceCopy (
HINF InfFile
)
{
INFCONTEXT ic;
TCHAR SrcObjectStr[MAX_ENCODED_RULE];
TCHAR DestObjectStr[MAX_ENCODED_RULE];
DATAOBJECT SrcObject, DestObject, DupObject;
BOOL b = TRUE;
FILTERRETURN fr;
//
// Look in INF for [ForceCopy] section
//
if (SetupFindFirstLine (InfFile, S_MERGE_FORCECOPY, NULL, &ic)) {
//
// For each line in this section, get the encoded object in
// field 0 (the source) and copy it to the encoded object in
// field 1 (the destination).
//
do {
*DestObjectStr = 0;
if (SetupGetStringField (&ic, 0, SrcObjectStr, MAX_ENCODED_RULE, NULL) &&
SetupGetStringField (&ic, 1, DestObjectStr, MAX_ENCODED_RULE, NULL)
) {
if (!(*DestObjectStr)) {
StringCopy (DestObjectStr, SrcObjectStr);
}
if (!CreateObjectStruct (SrcObjectStr, &SrcObject, WIN95OBJECT)) {
DEBUGMSG ((DBG_WARNING, "pForceCopy: Source object invalid (Section line %u of %s)",
ic.Line, g_InfFileName));
continue;
}
if (!CreateObjectStruct (DestObjectStr, &DestObject, WINNTOBJECT)) {
DEBUGMSG ((DBG_WARNING, "pForceCopy: Destination object invalid (Section line %u of %s)",
ic.Line, g_InfFileName));
FreeObjectStruct (&SrcObject);
continue;
}
if (b = DuplicateObjectStruct (&DupObject, &SrcObject)) {
if (b = CombineObjectStructs (&DupObject, &DestObject)) {
//
// Copy source to dest
//
fr = CopyObject (&SrcObject, &DupObject, NULL, NULL);
if (fr == FILTER_RETURN_FAIL) {
LOG ((LOG_ERROR, "Force Copy: CopyObject failed for %s=%s in %s", SrcObjectStr, DestObjectStr, g_InfFileName));
b = FALSE;
}
}
FreeObjectStruct (&DupObject);
}
FreeObjectStruct (&SrcObject);
FreeObjectStruct (&DestObject);
} else {
LOG ((LOG_ERROR, "Force Copy: syntax error in line %u of section %s in %s",
ic.Line, S_MERGE_FORCECOPY, g_InfFileName));
}
TickProgressBar ();
} while (b && SetupFindNextLine (&ic, &ic));
}
return TRUE;
}
BOOL
pForceCopyFromMemDb (
VOID
)
{
MEMDB_ENUM e;
TCHAR key [MEMDB_MAX];
TCHAR SrcObjectStr[MAX_ENCODED_RULE];
TCHAR DestObjectStr[MAX_ENCODED_RULE];
DATAOBJECT SrcObject, DestObject, DupObject;
BOOL b = TRUE;
FILTERRETURN fr;
//
// Look in MemDb for ForceCopy tree
//
MemDbBuildKey (key, MEMDB_CATEGORY_FORCECOPY, TEXT("*"), NULL, NULL);
if (MemDbEnumFirstValue (&e, key, MEMDB_ALL_SUBLEVELS, MEMDB_ENDPOINTS_ONLY)) {
//
// For each key here the offset points to the destination
//
do {
if (e.dwValue != 0) {
StringCopy (SrcObjectStr, e.szName);
if (MemDbBuildKeyFromOffset (e.dwValue, DestObjectStr, 1, NULL)) {
if (!(*DestObjectStr)) {
StringCopy (DestObjectStr, SrcObjectStr);
}
if (!CreateObjectStruct (SrcObjectStr, &SrcObject, WIN95OBJECT)) {
DEBUGMSG ((DBG_WARNING, "pForceCopyFromMemDb: Source object invalid %s",
SrcObjectStr));
continue;
}
if (!CreateObjectStruct (DestObjectStr, &DestObject, WINNTOBJECT)) {
DEBUGMSG ((DBG_WARNING, "pForceCopyFromMemDb: Destination object invalid %s",
DestObjectStr));
FreeObjectStruct (&SrcObject);
continue;
}
if (b = DuplicateObjectStruct (&DupObject, &SrcObject)) {
if (b = CombineObjectStructs (&DupObject, &DestObject)) {
//
// Copy source to dest
//
fr = CopyObject (&SrcObject, &DupObject, NULL, NULL);
if (fr == FILTER_RETURN_FAIL) {
LOG ((LOG_ERROR, "Force Copy from MemDb: CopyObject failed for %s=%s", SrcObjectStr, DestObjectStr));
b = FALSE;
}
}
FreeObjectStruct (&DupObject);
}
FreeObjectStruct (&SrcObject);
FreeObjectStruct (&DestObject);
}
}
TickProgressBar ();
} while (b && MemDbEnumNextValue (&e));
}
return TRUE;
}
#define S_MERGE_DELETEAFTERMIGRATION TEXT("Delete After Migration")
BOOL
pDeleteAfterMigration (
IN HINF InfFile
)
{
BOOL rSuccess = TRUE;
TCHAR objectString[MAX_ENCODED_RULE];
DATAOBJECT object;
INFCONTEXT ic;
HKEY key;
//
// Look in INF for [DeleteAfterMigration] section
//
if (SetupFindFirstLine (InfFile, S_MERGE_DELETEAFTERMIGRATION, NULL, &ic)) {
//
// For each line in this section, get the encoded object in
// field 0 and delete it from the registry.
//
do {
if (SetupGetStringField(&ic,0,objectString,MAX_ENCODED_RULE,NULL)) {
FixUpUserSpecifiedObject(objectString);
if (!CreateObjectStruct(objectString,&object,WINNTOBJECT)) {
LOG((
LOG_ERROR,
"Delete After Migration: ObjectString invalid. (Section line %u of %s)",
ic.Line,
g_InfFileName
));
continue;
}
//
// We have a good object. Delete it!
//
if (object.ValueName) {
//
// Value is specified. Delete it.
//
if (!RegDeleteValue(object.KeyPtr->OpenKey,object.ValueName)) {
DEBUGMSG((DBG_WARNING,"pDeleteAfterMigration: RegDeleteValue failed for %s [%s]",
object.KeyPtr->KeyString,
object.ValueName ? object.ValueName : TEXT("<DEFAULT>")
));
}
}
else {
key = GetRootKeyFromOffset (object.RootItem);
pSetupRegistryDelnode (key == HKEY_ROOT ? g_hKeyRootNT : key, object.KeyPtr->KeyString);
}
//
// Free our resources.
//
FreeObjectStruct(&object);
}
} while (SetupFindNextLine(&ic,&ic));
}
return rSuccess;
}
BOOL
pCreateRenameTable (
IN HINF InfFile,
OUT PVOID *RenameTablePtr
)
{
INFCONTEXT ic;
TCHAR SrcObjectStr[MAX_ENCODED_RULE];
TCHAR DestObjectStr[MAX_ENCODED_RULE];
LONG rc;
DATAOBJECT OrgOb;
DATAOBJECT NewOb;
PCTSTR DestStr;
//
// Look in INF for [Rename] section
//
if (SetupFindFirstLine (InfFile, S_MERGE_RENAME, NULL, &ic)) {
//
// Create string table
//
*RenameTablePtr = pSetupStringTableInitializeEx (sizeof (PCTSTR), 0);
if (!(*RenameTablePtr)) {
LOG ((LOG_ERROR, "Create Rename Table: Cannot allocate a string table"));
return FALSE;
}
do {
if (SetupGetStringField (&ic, 0, SrcObjectStr, MAX_ENCODED_RULE, NULL) &&
SetupGetStringField (&ic, 1, DestObjectStr, MAX_ENCODED_RULE, NULL)
) {
// Ignore bad lines
FixUpUserSpecifiedObject (SrcObjectStr);
FixUpUserSpecifiedObject (DestObjectStr);
if (!CreateObjectStruct (SrcObjectStr, &OrgOb, WIN95OBJECT)) {
DEBUGMSG ((DBG_WARNING, "pCreateRenameTable: Source object invalid (Section line %u of %s)",
ic.Line, g_InfFileName));
continue;
}
if (!CreateObjectStruct (DestObjectStr, &NewOb, WINNTOBJECT)) {
FreeObjectStruct (&OrgOb);
DEBUGMSG ((DBG_WARNING, "pCreateRenameTable: Dest object invalid (Section line %u of %s)",
ic.Line, g_InfFileName));
continue;
}
//
// Convert DestObjectStr into complete object string
//
if (!CombineObjectStructs (&OrgOb, &NewOb)) {
FreeObjectStruct (&NewOb);
FreeObjectStruct (&OrgOb);
DEBUGMSG ((DBG_WARNING, "pCreateRenameTable: Can't perform the rename (Section line %u in %s)",
ic.Line, g_InfFileName));
continue;
}
// Disable tree for destination object
OrgOb.ObjectType &= ~OT_TREE;
CreateObjectString (&OrgOb, DestObjectStr);
FreeObjectStruct (&NewOb);
FreeObjectStruct (&OrgOb);
DestStr = PoolMemDuplicateString (g_RenamePool, DestObjectStr);
if (!DestStr) {
break;
}
rc = pSetupStringTableAddStringEx (
*RenameTablePtr,
(PTSTR) SrcObjectStr,
STRTAB_CASE_INSENSITIVE,
(PBYTE) &DestStr,
sizeof (PCTSTR)
);
if (rc == -1) {
SetLastError (rc);
LOG ((LOG_ERROR, "Create Rename Table: Cannot add string to string table"));
break;
}
SetObjectStringFlag (SrcObjectStr, REGMERGE_95_RENAME, REGMERGE_95_RENAME);
SetObjectStringFlag (DestStr, REGMERGE_NT_SUPPRESS, REGMERGE_NT_MASK);
} else {
LOG ((LOG_ERROR, "Create Rename Table: syntax error in line %u of section %s in %s",
ic.Line, S_MERGE_RENAME, g_InfFileName));
}
TickProgressBar ();
} while (SetupFindNextLine (&ic, &ic));
} else {
return FALSE;
}
return TRUE;
}
BOOL
CopyRenameTableEntry (
PVOID StringTable,
LONG StringID,
PCTSTR SrcObjectStr,
PVOID ExtraData,
UINT ExtraDataSize,
LPARAM lParam
)
{
PCTSTR DestObjectStr = *((PCTSTR *) ExtraData);
DATAOBJECT SrcOb, DestOb;
FILTERRETURN fr = FILTER_RETURN_FAIL;
DWORD Val;
// See if src has been processed
if (MemDbGetValue (SrcObjectStr, &Val) && (Val & REGMERGE_95_RENAME_SUPPRESS)) {
return TRUE;
}
// If not, copy Win95 src to WinNT dest
if (CreateObjectStruct (SrcObjectStr, &SrcOb, WIN95OBJECT)) {
if (CreateObjectStruct (DestObjectStr, &DestOb, WINNTOBJECT)) {
fr = CopyObject (&SrcOb, &DestOb, SuppressFilter95, NULL);
FreeObjectStruct (&DestOb);
}
FreeObjectStruct (&SrcOb);
}
return fr != FILTER_RETURN_FAIL;
}
BOOL
pProcessRenameTable (
IN PVOID RenameTable
)
{
PCTSTR DataBuf;
return pSetupStringTableEnum (RenameTable, (PVOID) &DataBuf, sizeof (DataBuf), CopyRenameTableEntry, 0);
}
BOOL
pSpecialConversion (
IN HINF InfFile,
IN PCTSTR User,
IN PVOID RenameTable
)
{
INFCONTEXT ic;
TCHAR FunctionStr[MAX_ENCODED_RULE];
TCHAR SrcObjectStr[MAX_ENCODED_RULE];
TCHAR RenamedObjectStr[MAX_ENCODED_RULE];
PROCESSINGFN Fn;
PVOID Arg;
//
// Look in INF for [SpecialConversion] section
//
if (SetupFindFirstLine (InfFile, S_MERGE_WIN9X_CONVERSION, NULL, &ic)) {
//
// For each line, get the function and the source object, then call
// the function.
//
do {
if (SetupGetStringField (&ic, 0, FunctionStr, MAX_ENCODED_RULE, NULL) &&
SetupGetStringField (&ic, 1, SrcObjectStr, MAX_ENCODED_RULE, NULL)
) {
FixUpUserSpecifiedObject (SrcObjectStr);
Fn = RuleHlpr_GetFunctionAddr (FunctionStr, &Arg);
if (!Fn) {
LOG ((LOG_ERROR, "Special Conversion: Invalid function %s in %s", FunctionStr, g_InfFileName));
continue;
}
CreateRenamedObjectString (RenameTable, SrcObjectStr, RenamedObjectStr);
if (!Fn (SrcObjectStr, RenamedObjectStr, User, Arg)) {
if (GetLastError () == ERROR_SUCCESS) {
continue;
}
LOG ((LOG_ERROR, "Processing of Special Conversion was aborted because %s failed.", FunctionStr));
break;
}
SetObjectStringFlag (
SrcObjectStr,
REGMERGE_95_SUPPRESS|REGMERGE_95_RENAME_SUPPRESS,
REGMERGE_95_SUPPRESS|REGMERGE_95_RENAME_SUPPRESS
);
SetObjectStringFlag (RenamedObjectStr, REGMERGE_NT_SUPPRESS, REGMERGE_NT_MASK);
} else {
LOG ((LOG_ERROR, "Special Conversion: syntax error in line %u of section %s in %s",
ic.Line, S_MERGE_WIN9X_CONVERSION, g_InfFileName));
}
TickProgressBar ();
} while (SetupFindNextLine (&ic, &ic));
}
return TRUE;
}
BOOL
SetFlagsForObject (
IN HINF InfFile,
IN PCTSTR Section,
IN DWORD Flag,
IN DWORD RemoveFlag
)
{
INFCONTEXT ic;
TCHAR SrcObjectStr[MAX_ENCODED_RULE];
//
// Look in INF for section
//
if (SetupFindFirstLine (InfFile, Section, NULL, &ic)) {
//
// For each line, get the object and mark it as suppressed.
//
do {
if (SetupGetStringField (&ic, 1, SrcObjectStr, MAX_ENCODED_RULE, NULL)
) {
FixUpUserSpecifiedObject (SrcObjectStr);
SetObjectStringFlag (SrcObjectStr, Flag, RemoveFlag);
} else {
LOG ((LOG_ERROR, "Set Flags For Object: syntax error in line %u of section %s in %s",
ic.Line, Section, g_InfFileName));
}
TickProgressBar ();
} while (SetupFindNextLine (&ic, &ic));
} else {
DEBUGMSG ((DBG_VERBOSE, "SetFlagsForObject: Section %s can't be found", Section));
}
return TRUE;
}
BOOL
pProcessSuppressList (
IN HINF InfFile,
IN PCTSTR SectionName
)
{
return SetFlagsForObject (
InfFile,
SectionName,
REGMERGE_95_SUPPRESS,
REGMERGE_95_SUPPRESS
);
}
BOOL
pProcessHardwareSuppressList (
IN HINF InfFile
)
{
return SetFlagsForObject (InfFile, S_MERGE_WIN9X_SUPPRESS_HW, REGMERGE_95_SUPPRESS, REGMERGE_95_SUPPRESS);
}
BOOL
pSuppressNTDefaults (
IN HINF InfFile,
IN PCTSTR SectionName
)
{
//
// The objects listed in Suppress WinNT Settings are enumerated,
// and they are blocked from being transferred from the NT default
// user to the new user.
//
return SetFlagsForObject (
InfFile,
SectionName,
REGMERGE_NT_SUPPRESS,
REGMERGE_NT_SUPPRESS
);
}
BOOL
pDontCombineWithDefaults (
IN HINF InfFile,
IN PCTSTR SectionName
)
{
//
// The objects listed in Merge WinNT with Win9x are enumerated,
// and they are blocked from being transferred from the NT default
// user to the new user. In addition, they are put in a list
// to be processed at the end of user registry migration. This
// last step uses CombineFilter to make sure the NT values do
// not overwrite the 9x values.
//
return SetFlagsForObject (
InfFile,
SectionName,
REGMERGE_NT_IGNORE_DEFAULTS,
REGMERGE_NT_IGNORE_DEFAULTS
);
}
BOOL
pForceNTDefaults (
IN HINF InfFile,
IN PCTSTR SectionName
)
{
//
// The objects listed in Force WinNT Settings are enumerated,
// and they are blocked from being processed during the general
// 9x to NT copy. In addition, they are put in a list to be
// processed at the end of user registry migration. This last
// step forces the entire key to be copied from the default
// user to the new user, overwriting any previously migrated
// settings.
//
// It is important to note that the special conversion functions
// are not suppressed here, but the converted settings may be
// overwritten.
//
return SetFlagsForObject (
InfFile,
SectionName,
REGMERGE_NT_PRIORITY_NT|REGMERGE_95_SUPPRESS,
REGMERGE_NT_PRIORITY_NT|REGMERGE_95_SUPPRESS
);
}
BOOL
pForceNTDefaultsHack (
IN HINF InfFile,
IN PCTSTR SectionName
)
{
//
// Take away the REGMERGE_95_SUPPRESS flag now, because the general
// 9x merge has completed, but we get confused between an actual
// suppress and a suppress done for the priority-nt case.
//
return SetFlagsForObject (
InfFile,
SectionName,
REGMERGE_NT_PRIORITY_NT,
REGMERGE_NT_PRIORITY_NT|REGMERGE_95_SUPPRESS
);
}
FILTERRETURN
SuppressFilter95 (
IN CPDATAOBJECT SrcObjectPtr,
IN CPDATAOBJECT DestObjectPtr, OPTIONAL
IN FILTERTYPE FilterType,
IN PVOID DontCare
)
{
TCHAR ObStr[MAX_ENCODED_RULE];
DWORD Val;
PTSTR p, q, r;
TCHAR Node[MEMDB_MAX];
if (FilterType == FILTER_CREATE_KEY) {
//
// Check if this tree is suppressed
//
MYASSERT (SrcObjectPtr->ObjectType & OT_TREE);
MYASSERT (SrcObjectPtr->KeyPtr);
MYASSERT (!(SrcObjectPtr->ValueName));
// Query setting for HKR\Sub\Key\*
CreateObjectString (SrcObjectPtr, ObStr);
if (MemDbGetValue (ObStr, &Val)) {
if (Val & REGMERGE_95_SUPPRESS) {
return FILTER_RETURN_DONE;
}
if (!g_ProcessRenameTable && (Val & REGMERGE_95_RENAME)) {
return FILTER_RETURN_DONE;
}
}
// If key is a GUID and GUID is suppressed, suppress the tree
p = (PTSTR) SrcObjectPtr->ChildKey;
if (p && _tcsnextc (p) == TEXT('{')) {
// Look for matching curly brace
q = _tcschr (p, TEXT('}'));
if (q) {
q = _tcsinc (q);
// Create GUIDS\{a-b-c-d-e}
*Node = 0;
r = _tcsappend (Node, MEMDB_CATEGORY_GUIDS);
r = _tcsappend (r, TEXT("\\"));
StringCopyAB (r, p, q);
// Look for match
if (MemDbGetValue (Node, NULL)) {
DEBUGMSG ((DBG_VERBOSE, "Suppressed %s found in %s", Node, ObStr));
return FILTER_RETURN_DONE;
}
}
}
}
else if (FilterType == FILTER_PROCESS_VALUES) {
//
// Check if this node is suppressed
//
MYASSERT (!(SrcObjectPtr->ObjectType & OT_TREE));
MYASSERT (SrcObjectPtr->KeyPtr);
MYASSERT (!(SrcObjectPtr->ValueName));
CreateObjectString (SrcObjectPtr, ObStr);
// Query setting for HKR\Sub\Key
if (!MemDbGetValue (ObStr, &Val)) {
Val = 0;
}
if (Val & REGMERGE_95_SUPPRESS) {
return FILTER_RETURN_HANDLED;
}
if (!g_ProcessRenameTable && (Val & REGMERGE_95_RENAME)) {
return FILTER_RETURN_HANDLED;
}
}
else if (FilterType == FILTER_VALUENAME_ENUM) {
//
// Check if this value is suppressed
//
MYASSERT (!(SrcObjectPtr->ObjectType & OT_TREE));
MYASSERT (SrcObjectPtr->KeyPtr);
MYASSERT (SrcObjectPtr->ValueName);
CreateObjectString (SrcObjectPtr, ObStr);
// If value name is a GUID and GUID is suppressed, suppress the value
p = (PTSTR) SrcObjectPtr->ValueName;
if (_tcsnextc (p) == TEXT('{')) {
MemDbBuildKey (Node, MEMDB_CATEGORY_GUIDS, NULL, NULL, p);
if (MemDbGetValue (Node, NULL)) {
return FILTER_RETURN_HANDLED;
}
}
if (!MemDbGetValue (ObStr, &Val)) {
Val = 0;
}
if (Val & REGMERGE_95_SUPPRESS) {
return FILTER_RETURN_HANDLED;
}
if (!g_ProcessRenameTable && (Val & REGMERGE_95_RENAME)) {
return FILTER_RETURN_HANDLED;
}
}
else if (FilterType == FILTER_VALUE_COPY) {
//
// Don't copy if value has a suppressed GUID
//
p = pGetStringFromObjectData (SrcObjectPtr);
if (p && _tcsnextc (p) == TEXT('{')) {
MemDbBuildKey (Node, MEMDB_CATEGORY_GUIDS, NULL, NULL, p);
if (MemDbGetValue (Node, NULL)) {
return FILTER_RETURN_HANDLED;
}
}
}
return FILTER_RETURN_CONTINUE;
}
FILTERRETURN
SuppressFilterNT (
IN CPDATAOBJECT SrcObjectPtr,
IN CPDATAOBJECT DestObjectPtr, OPTIONAL
IN FILTERTYPE FilterType,
IN PVOID DontCare
)
{
TCHAR ObStr[MAX_ENCODED_RULE];
DWORD Val;
PTSTR p;
if (FilterType == FILTER_CREATE_KEY) {
//
// Check if this tree is suppressed
//
MYASSERT (DestObjectPtr->ObjectType & OT_TREE);
MYASSERT (DestObjectPtr->KeyPtr);
MYASSERT (!(DestObjectPtr->ValueName));
CreateObjectString (DestObjectPtr, ObStr);
if (MemDbGetValue (ObStr, &Val) && (Val & REGMERGE_NT_MASK)) {
return FILTER_RETURN_DONE;
}
}
else if (FilterType == FILTER_PROCESS_VALUES) {
DATAOBJECT CopyOfDestOb;
DWORD rc;
DWORD ValueCount;
//
// Does destination already exist?
//
CopyMemory (&CopyOfDestOb, DestObjectPtr, sizeof (DATAOBJECT));
if (OpenObject (&CopyOfDestOb)) {
//
// Does it have values?
//
MYASSERT (!IsWin95Object (&CopyOfDestOb));
rc = RegQueryInfoKey (
CopyOfDestOb.KeyPtr->OpenKey,
NULL, // class
NULL, // class size
NULL, // reserved
NULL, // subkey count
NULL, // max subkey length
NULL, // max class length
&ValueCount,
NULL, // max value name size
NULL, // max value size
NULL, // security
NULL // last changed time
);
if (rc == ERROR_SUCCESS && ValueCount > 0) {
CloseObject (&CopyOfDestOb);
return FILTER_RETURN_HANDLED;
}
}
//
// Check if this node is suppressed
//
MYASSERT (DestObjectPtr->ObjectType & OT_TREE);
MYASSERT (DestObjectPtr->KeyPtr);
MYASSERT (!(DestObjectPtr->ValueName));
CreateObjectString (DestObjectPtr, ObStr);
p = _tcsrchr (ObStr, TEXT('\\'));
if (p) {
*p = 0;
}
if (MemDbGetValue (ObStr, &Val) && (Val & REGMERGE_NT_MASK)) {
return FILTER_RETURN_HANDLED;
}
}
else if (FilterType == FILTER_VALUENAME_ENUM) {
//
// Check if this value is suppressed
//
MYASSERT (!(DestObjectPtr->ObjectType & OT_TREE));
MYASSERT (DestObjectPtr->KeyPtr);
MYASSERT (DestObjectPtr->ValueName);
CreateObjectString (DestObjectPtr, ObStr);
if (MemDbGetValue (ObStr, &Val) && (Val & REGMERGE_NT_MASK)) {
return FILTER_RETURN_HANDLED;
}
}
return FILTER_RETURN_CONTINUE;
}
FILTERRETURN
CombineFilter (
IN CPDATAOBJECT SrcObjectPtr,
IN CPDATAOBJECT DestObjectPtr, OPTIONAL
IN FILTERTYPE FilterType,
IN PVOID DontCare
)
{
BOOL b;
if (FilterType == FILTER_VALUE_COPY) {
//
// Check if destination already exists in the registry
//
MYASSERT (!(SrcObjectPtr->ObjectType & OT_TREE));
MYASSERT (SrcObjectPtr->KeyPtr);
MYASSERT (SrcObjectPtr->ValueName);
MYASSERT (!(DestObjectPtr->ObjectType & OT_TREE));
MYASSERT (DestObjectPtr->KeyPtr);
MYASSERT (DestObjectPtr->ValueName);
b = CheckIfNtKeyExists (DestObjectPtr);
if (b) {
return FILTER_RETURN_HANDLED;
} else if (GetLastError() != ERROR_SUCCESS) {
return FILTER_RETURN_FAIL;
}
}
return FILTER_RETURN_CONTINUE;
}
FILTERRETURN
pSuppressDefaultUserFilter (
IN CPDATAOBJECT SrcObjectPtr,
IN CPDATAOBJECT DestObjectPtr, OPTIONAL
IN FILTERTYPE FilterType,
IN PVOID DontCare
)
{
TCHAR ObStr[MAX_ENCODED_RULE];
DWORD Val;
PTSTR p;
if (FilterType == FILTER_CREATE_KEY) {
//
// Check if this tree is suppressed
//
MYASSERT (DestObjectPtr->ObjectType & OT_TREE);
MYASSERT (DestObjectPtr->KeyPtr);
MYASSERT (!(DestObjectPtr->ValueName));
CreateObjectString (DestObjectPtr, ObStr);
if (MemDbGetValue (ObStr, &Val) && (Val & REGMERGE_NT_IGNORE_DEFAULTS)) {
return FILTER_RETURN_DONE;
}
}
else if (FilterType == FILTER_PROCESS_VALUES) {
//
// Check if this node is suppressed
//
MYASSERT (DestObjectPtr->ObjectType & OT_TREE);
MYASSERT (DestObjectPtr->KeyPtr);
MYASSERT (!(DestObjectPtr->ValueName));
CreateObjectString (DestObjectPtr, ObStr);
p = _tcsrchr (ObStr, TEXT('\\'));
if (p) {
*p = 0;
}
if (MemDbGetValue (ObStr, &Val) && (Val & REGMERGE_NT_IGNORE_DEFAULTS)) {
return FILTER_RETURN_HANDLED;
}
}
else if (FilterType == FILTER_VALUENAME_ENUM) {
//
// Check if this value is suppressed
//
MYASSERT (!(DestObjectPtr->ObjectType & OT_TREE));
MYASSERT (DestObjectPtr->KeyPtr);
MYASSERT (DestObjectPtr->ValueName);
CreateObjectString (DestObjectPtr, ObStr);
if (MemDbGetValue (ObStr, &Val) && (Val & REGMERGE_NT_IGNORE_DEFAULTS)) {
return FILTER_RETURN_HANDLED;
}
}
return CombineFilter (SrcObjectPtr, DestObjectPtr, FilterType, DontCare);
}
FILTERRETURN
CopyNoOverwriteFilter (
IN CPDATAOBJECT SrcObjectPtr,
IN CPDATAOBJECT DestObjectPtr, OPTIONAL
IN FILTERTYPE FilterType,
IN PVOID DontCare
)
{
FILTERRETURN fr;
fr = SuppressFilter95 (SrcObjectPtr, DestObjectPtr, FilterType, DontCare);
if (fr != FILTER_RETURN_CONTINUE) {
return fr;
}
return CombineFilter (SrcObjectPtr, DestObjectPtr, FilterType, DontCare);
}
BOOL
pMergeWin95WithUser (
IN PVOID RenameTable
)
{
DATAOBJECT SrcOb, DestOb;
BOOL b;
FILTERRETURN fr;
//
// Copy unsuppressed Win95 keys to NT user hive
//
b = CreateObjectStruct (TEXT("HKR\\*"), &SrcOb, WIN95OBJECT);
MYASSERT (b);
b = CreateObjectStruct (TEXT("HKR\\*"), &DestOb, WINNTOBJECT);
MYASSERT (b);
fr = CopyObject (&SrcOb, &DestOb, SuppressFilter95, NULL);
FreeObjectStruct (&SrcOb);
FreeObjectStruct (&DestOb);
if (fr == FILTER_RETURN_FAIL) {
LOG ((LOG_ERROR, "Merge Win95 With User: CopyObject failed"));
return FALSE;
}
return TRUE;
}
VOID
RegistryCombineWorker (
DWORD Flag,
FILTERFUNCTION FilterFn,
PCTSTR MemDbRoot,
PCTSTR SrcRoot,
DWORD SrcObjectType
)
{
MEMDB_ENUM e;
TCHAR SrcRegKey[MEMDB_MAX];
TCHAR DestRegKey[MEMDB_MAX];
PTSTR SrcPtr, DestPtr;
DATAOBJECT SrcOb, DestOb;
FILTERRETURN fr;
TCHAR Pattern[32];
wsprintf (Pattern, TEXT("%s\\*"), MemDbRoot);
//
// Enumerate all keys in memdb and call CopyObject for them
//
*SrcRegKey = 0;
*DestRegKey = 0;
SrcPtr = _tcsappend (SrcRegKey, SrcRoot);
SrcPtr = _tcsappend (SrcPtr, TEXT("\\"));
DestPtr = _tcsappend (DestRegKey, MemDbRoot);
DestPtr = _tcsappend (DestPtr, TEXT("\\"));
if (MemDbEnumFirstValue (
&e,
Pattern,
MEMDB_ALL_SUBLEVELS,
MEMDB_ENDPOINTS_ONLY
)) {
do {
if ((e.dwValue & REGMERGE_NT_MASK) & Flag) {
StringCopy (SrcPtr, e.szName);
StringCopy (DestPtr, e.szName);
if (!CreateObjectStruct (SrcRegKey, &SrcOb, SrcObjectType)) {
LOG ((LOG_ERROR, "Merge NT Defaults With User: Can't create object for %s", SrcRegKey));
continue;
}
if (!CreateObjectStruct (DestRegKey, &DestOb, WINNTOBJECT)) {
FreeObjectStruct (&SrcOb);
LOG ((LOG_ERROR, "Merge NT Defaults With User: Can't create object for %s", SrcRegKey));
continue;
}
fr = CopyObject (&SrcOb, &DestOb, FilterFn, NULL);
if (fr == FILTER_RETURN_FAIL) {
LOG ((LOG_ERROR, "Merge NT Defaults With User: Can't copy %s to %s", SrcRegKey, DestRegKey));
}
FreeObjectStruct (&SrcOb);
FreeObjectStruct (&DestOb);
}
TickProgressBar ();
} while (MemDbEnumNextValue (&e));
}
}
BOOL
pMergeNTDefaultsWithUser (
HINF hInf
)
{
DATAOBJECT SrcOb, DestOb;
FILTERRETURN fr;
BOOL b;
//
// Copy unsuppressed NT defaults to NT user hive
//
b = CreateObjectStruct (
TEXT("HKLM\\") S_MAPPED_DEFAULT_USER_KEY TEXT("\\*"),
&SrcOb,
WINNTOBJECT
);
MYASSERT (b);
b = CreateObjectStruct (TEXT("HKR\\*"), &DestOb, WINNTOBJECT);
MYASSERT (b);
__try {
b = FALSE;
fr = CopyObject (&SrcOb, &DestOb, SuppressFilterNT, NULL);
if (fr == FILTER_RETURN_FAIL) {
LOG ((LOG_ERROR, "Merge NT Defaults With User: CopyObject failed"));
__leave;
}
//
// Copy forced NT defaults to NT user hive, then copy all NT defaults
// that need to be combined with Win95 settings.
//
RegistryCombineWorker (
REGMERGE_NT_PRIORITY_NT,
NULL,
TEXT("HKR"),
TEXT("HKLM\\") S_MAPPED_DEFAULT_USER_KEY,
WINNTOBJECT
);
fr = CopyObject (&SrcOb, &DestOb, pSuppressDefaultUserFilter, NULL);
if (fr == FILTER_RETURN_FAIL) {
LOG ((LOG_ERROR, "Combine NT Defaults With User: CopyObject failed"));
__leave;
}
b = TRUE;
}
__finally {
FreeObjectStruct (&SrcOb);
FreeObjectStruct (&DestOb);
}
return b;
}
BOOL
pCopyWin9xValuesNotInNt (
HINF hInf
)
{
DATAOBJECT SrcOb, DestOb;
FILTERRETURN fr;
BOOL b;
//
// Copy Win9x values that NT does not have
//
b = CreateObjectStruct (
TEXT("HKLM\\*"),
&SrcOb,
WIN95OBJECT
);
MYASSERT (b);
b = CreateObjectStruct (TEXT("HKR\\*"), &DestOb, WINNTOBJECT);
MYASSERT (b);
__try {
b = FALSE;
fr = CopyObject (&SrcOb, &DestOb, SuppressFilterNT, NULL);
if (fr == FILTER_RETURN_FAIL) {
LOG ((LOG_ERROR, "Merge NT Defaults With User: CopyObject failed"));
__leave;
}
//
// Copy forced NT defaults to NT user hive, then copy all NT defaults
// that need to be combined with Win95 settings.
//
RegistryCombineWorker (
REGMERGE_NT_PRIORITY_NT,
NULL,
TEXT("HKR"),
TEXT("HKLM\\") S_MAPPED_DEFAULT_USER_KEY,
WINNTOBJECT
);
fr = CopyObject (&SrcOb, &DestOb, pSuppressDefaultUserFilter, NULL);
if (fr == FILTER_RETURN_FAIL) {
LOG ((LOG_ERROR, "Combine NT Defaults With User: CopyObject failed"));
__leave;
}
b = TRUE;
}
__finally {
FreeObjectStruct (&SrcOb);
FreeObjectStruct (&DestOb);
}
return b;
}
BOOL
pMergeWin95WithSystem (
VOID
)
/*++
Routine Description:
pMergeWin95WithSystem copies the Win95 registry to NT, skipping values
that already exist on NT.
Arguments:
none
Return Value:
TRUE if success, FALSE if failure.
--*/
{
RegistryCombineWorker (
REGMERGE_NT_PRIORITY_NT,
CopyNoOverwriteFilter,
TEXT("HKLM"), // memdb root and dest root
TEXT("HKLM"), // source root
WIN95OBJECT
);
return TRUE;
}
BOOL
pCopyWin95ToSystem (
VOID
)
/*++
Routine Description:
pCopyWin95ToSystem copies all Win95 settings to NT, unless the setting
is supressed. This achieves a copy with overwrite capability.
Arguments:
none
Return Value:
TRUE if success, FALSE if failure.
--*/
{
DATAOBJECT SrcOb, DestOb;
BOOL b;
FILTERRETURN fr;
b = CreateObjectStruct (TEXT("HKLM\\*"), &SrcOb, WIN95OBJECT);
MYASSERT (b);
b = CreateObjectStruct (TEXT("HKLM\\*"), &DestOb, WINNTOBJECT);
MYASSERT (b);
fr = CopyObject (&SrcOb, &DestOb, SuppressFilter95, NULL);
FreeObjectStruct (&SrcOb);
FreeObjectStruct (&DestOb);
if (fr == FILTER_RETURN_FAIL) {
LOG ((LOG_ERROR, "Copy Win95 To System: CopyObject failed"));
return FALSE;
}
return TRUE;
}
BOOL
pSpecialConversionNT (
IN HINF InfFile,
IN PCTSTR User,
IN BOOL PerUser
)
{
INFCONTEXT ic;
DATAOBJECT SrcOb, DestOb;
TCHAR FunctionStr[MAX_ENCODED_RULE];
TCHAR SrcObjectStr[MAX_ENCODED_RULE];
TCHAR DestObjectStr[MAX_ENCODED_RULE];
PROCESSINGFN Fn;
PVOID Arg;
//
// Look in INF for [SpecialConversionNT] section
//
if (SetupFindFirstLine (InfFile, S_MERGE_WINNT_CONVERSION, NULL, &ic)) {
//
// For each line, get the function and the source object, then call
// the function.
//
do {
if (SetupGetStringField (&ic, 0, FunctionStr, MAX_ENCODED_RULE, NULL) &&
SetupGetStringField (&ic, 1, DestObjectStr, MAX_ENCODED_RULE, NULL)
) {
FixUpUserSpecifiedObject (DestObjectStr);
Fn = RuleHlpr_GetFunctionAddr (FunctionStr, &Arg);
if (!Fn) {
LOG ((LOG_ERROR, "Special Conversion: Invalid function %s in %s", FunctionStr, g_InfFileName));
continue;
}
if (PerUser) {
//
// Make source off of HKLM\MappedDefaultUser
//
if (!CreateObjectStruct (DestObjectStr, &SrcOb, WINNTOBJECT)) {
continue;
}
if (!(SrcOb.RootItem)) {
LOG ((LOG_ERROR, "Special Conversion NT: Invalid function object %s", DestObjectStr));
FreeObjectStruct (&SrcOb);
continue;
}
CreateObjectStruct (TEXT("HKLM"), &DestOb, WINNTOBJECT);
CombineObjectStructs (&SrcOb, &DestOb);
StringCopy (SrcObjectStr, S_MAPPED_DEFAULT_USER_KEY TEXT("\\"));
CreateObjectString (&SrcOb, GetEndOfString (SrcObjectStr));
FreeObjectStruct (&DestOb);
FreeObjectStruct (&SrcOb);
} else {
if (!CreateObjectStruct (DestObjectStr, &SrcOb, WINNTOBJECT)) {
continue;
}
if (!(SrcOb.RootItem)) {
LOG ((LOG_ERROR, "Special Conversion NT: Invalid function object %s", DestObjectStr));
FreeObjectStruct (&SrcOb);
continue;
}
CreateObjectString (&SrcOb, SrcObjectStr);
FreeObjectStruct (&SrcOb);
}
if (!Fn (SrcObjectStr, PerUser ? DestObjectStr : SrcObjectStr, User, Arg)) {
if (GetLastError () == ERROR_SUCCESS) {
continue;
}
LOG ((LOG_ERROR, "Processing of Special Conversion was aborted because %s failed.", FunctionStr));
break;
}
SetObjectStringFlag (SrcObjectStr, REGMERGE_NT_SUPPRESS, REGMERGE_NT_MASK);
} else {
LOG ((LOG_ERROR, "Special Conversion NT: syntax error in line %u of section %s in %s",
ic.Line, S_MERGE_WINNT_CONVERSION, g_InfFileName));
}
TickProgressBar ();
} while (SetupFindNextLine (&ic, &ic));
}
return TRUE;
}
BOOL
SuppressWin95Object (
IN PCTSTR ObjectStr
)
{
return SetObjectStringFlag (ObjectStr, REGMERGE_95_SUPPRESS, REGMERGE_95_SUPPRESS);
}
BOOL
CheckIfNtKeyExists (
IN CPDATAOBJECT SrcObjectPtr
)
/*++
Routine Description:
CheckIfNtKeyExists takes a 9x object and tests to see if the same NT
setting exists. The 9x object must have a key and value name.
Arguments:
SrcObjectPtr - Specifies the 9x object to test.
Return Value:
TRUE if the object exists in NT, FALSE if it doesn't or if an error occurs.
GetLastError indicates the error (if any).
--*/
{
DATAOBJECT NtObject;
BOOL b;
PCSTR value1;
PCSTR value2;
PCWSTR value3;
PCWSTR oldValueName;
HKEY oldRoot;
if (!DuplicateObjectStruct (&NtObject, SrcObjectPtr)) {
LOG ((LOG_ERROR, "Combine Filter: destination is invalid"));
return FALSE;
}
SetPlatformType (&NtObject, FALSE);
b = OpenObject (&NtObject);
if (!b && g_DuHandle) {
oldRoot = GetRegRoot();
SetRegRoot (g_DuHandle);
b = OpenObject (&NtObject);
SetRegRoot (oldRoot);
}
if (b) {
b = ReadObject (&NtObject);
if (!b) {
if (OurGetACP() == 932) {
//
// Katakana special case
//
oldValueName = NtObject.ValueName;
value1 = ConvertWtoA (NtObject.ValueName);
value2 = ConvertSBtoDB (NULL, value1, NULL);
value3 = ConvertAtoW (value2);
NtObject.ValueName = value3;
FreeObjectVal (&NtObject);
b = ReadObject (&NtObject);
FreeConvertedStr (value3);
FreePathStringA (value2);
FreeConvertedStr (value1);
NtObject.ValueName = oldValueName;
}
}
}
FreeObjectStruct (&NtObject);
SetLastError (ERROR_SUCCESS);
return b;
}