windows-nt/Source/XPSP1/NT/base/ntsetup/win95upg/w95upgnt/merge/hwprof.c

898 lines
23 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
hwprof.c
Abstract:
Hardware profile merge code
Author:
Jim Schmidt (jimschm) 29-May-1997
Revision History:
--*/
#include "pch.h"
#include "mergep.h"
HASHTABLE g_SoftwareDefaultListHash = NULL;
typedef struct _HARDWARE_PROFILE {
DWORD NumberOnWin9x;
} HARDWARE_PROFILE, *PHARDWARE_PROFILE;
GROWLIST g_HardwareProfileList = GROWLIST_INIT;
BOOL
pCreateDefaultKey (
LPCTSTR BaseRegStr
);
BOOL
pCopyHwProfileProperties (
IN DWORD ProfileSrcId,
IN DWORD ProfileDestId
);
FILTERRETURN
pHwProfileEnumFilter (
IN CPDATAOBJECT SrcObjectPtr,
IN CPDATAOBJECT Unused, OPTIONAL
IN FILTERTYPE FilterType,
IN LPVOID FilterArg OPTIONAL
);
BOOL
pCopyHwProfileConfigData (
IN DWORD ProfileSrcId,
IN DWORD ProfileDestId
);
VOID
pDeleteProfilesConfigValues(
IN DWORD ConfigNumber
);
BOOL
pDeleteDefaultKey (
IN LPCTSTR BaseRegStr
);
DWORD
pGetCurrentConfig (
VOID
);
BOOL
pCopyCurrentConfig (
VOID
);
VOID
pProcessSoftwareDefaultList(
IN HINF InfFile,
IN PCTSTR Section
);
VOID
pFreeSoftwareDefaultList(
VOID
);
VOID
pMigrateHardwareProfiles(
VOID
);
BOOL
CopyHardwareProfiles (
IN HINF InfFile
)
{
BOOL b;
DATAOBJECT Win9xOb;
//
// Move current hardware profile into Default key
//
if (!pCreateDefaultKey (S_IDCONFIGDB_HW_KEY)) {
LOG ((LOG_ERROR, "Unable to complete CopyHardwareProfiles"));
return FALSE;
}
if (!pCreateDefaultKey (S_NT_CONFIG_KEY)) {
LOG ((LOG_ERROR, "Unable to complete CopyHardwareProfiles (2)"));
return FALSE;
}
//
// Enumerate all Win9x hardware profiles and copy each one
//
pProcessSoftwareDefaultList(InfFile, S_MERGE_WIN9X_SUPPRESS_SFT_D);
b = CreateObjectStruct (S_9X_CONFIG_KEY S_TREE, &Win9xOb, WIN95OBJECT);
MYASSERT(b);
b = FILTER_RETURN_FAIL != CopyObject (&Win9xOb,
NULL,
pHwProfileEnumFilter,
(PVOID)pGetCurrentConfig());
pFreeSoftwareDefaultList();
pMigrateHardwareProfiles();
//
// Clean up Default key
//
pDeleteDefaultKey (S_IDCONFIGDB_HW_KEY);
pDeleteDefaultKey (S_NT_CONFIG_KEY);
//
// Set the current config value
//
// b = pCopyCurrentConfig();
FreeObjectStruct (&Win9xOb);
return b;
}
FILTERRETURN
pHwProfileSuppressFilter (
IN CPDATAOBJECT SrcObjectPtr,
IN CPDATAOBJECT DestObjectPtr, OPTIONAL
IN FILTERTYPE FilterType,
IN LPVOID UnusedArg OPTIONAL
)
{
TCHAR ObStr[MAX_ENCODED_RULE];
LPTSTR p;
TCHAR Node[MEMDB_MAX];
if (FilterType == FILTER_CREATE_KEY) {
// Create empty key is unnecessary
return FILTER_RETURN_HANDLED;
}
else if (FilterType == FILTER_KEY_ENUM ||
FilterType == FILTER_PROCESS_VALUES ||
FilterType == FILTER_VALUENAME_ENUM
) {
// Make p point to HKLM\Config\0001\...
CreateObjectString (SrcObjectPtr, ObStr);
p = ObStr;
// Make p point to \Config\0001\subkey
p = _tcschr (p, TEXT('\\'));
if (p) {
// Make p point to \0001\subkey
p = _tcschr (_tcsinc (p), TEXT('\\'));
if (p) {
// Make p point to \subkey
p = _tcschr (_tcsinc (p), TEXT('\\'));
if (p) {
// Make p point to subkey
p = _tcsinc (p);
} else {
p = S_EMPTY;
}
}
}
if (!p) {
DEBUGMSG ((
DBG_WHOOPS,
"pHwProfileSuppressFilter: Not a hardware profile key: %s",
ObStr
));
return FILTER_RETURN_FAIL;
}
//
// If an entry exists in memdb's HKCC category, we have a
// suppression match
//
wsprintf (Node, TEXT("HKCC\\%s"), p);
if (MemDbGetValue (Node, NULL)) {
return FILTER_RETURN_HANDLED;
}
}
return FILTER_RETURN_CONTINUE;
}
VOID
pProcessSoftwareDefaultList(
IN HINF InfFile,
IN PCTSTR Section
)
{
INFCONTEXT ic;
TCHAR SrcObjectStr[MAX_ENCODED_RULE];
g_SoftwareDefaultListHash = HtAllocW();
if(!g_SoftwareDefaultListHash){
LOG ((LOG_ERROR, "pProcessSoftwareDefaultList: Can't create hash table"));
return;
}
if(SetupFindFirstLine (InfFile, Section, NULL, &ic)){
do{
if(SetupGetStringField (&ic, 1, SrcObjectStr, MAX_ENCODED_RULE, NULL)){
FixUpUserSpecifiedObject(SrcObjectStr);
HtAddString(g_SoftwareDefaultListHash, SrcObjectStr);
}
else{
LOG ((LOG_ERROR, "pProcessSoftwareDefaultList: syntax error in line %u of section %s in wkstamig.inf",
ic.Line, Section));
}
} while (SetupFindNextLine (&ic, &ic));
}
else{
DEBUGMSG ((DBG_VERBOSE, "pProcessSoftwareDefaultList: Section %s can't be found", Section));
}
}
VOID
pFreeSoftwareDefaultList(
VOID
)
{
INFCONTEXT ic;
TCHAR SrcObjectStr[MAX_ENCODED_RULE];
if(g_SoftwareDefaultListHash){
HtFree(g_SoftwareDefaultListHash);
g_SoftwareDefaultListHash = NULL;
}
}
FILTERRETURN
pHwSoftwareDefaultDetectFilter (
IN CPDATAOBJECT SrcObjectPtr,
IN CPDATAOBJECT DestObjectPtr, OPTIONAL
IN FILTERTYPE FilterType,
IN LPVOID Arg
)
{
TCHAR ObStr[MAX_ENCODED_RULE];
LPTSTR p;
TCHAR Node[MEMDB_MAX];
BOOL * notDefault;
if(!Arg){
MYASSERT(FALSE);
return FILTER_RETURN_FAIL;
}
notDefault = Arg;
if (FilterType == FILTER_VALUENAME_ENUM){
// Make p point to HKLM\Config\0001\...
CreateObjectString (SrcObjectPtr, ObStr);
p = ObStr;
// Make p point to \Config\0001\Software\subkey
p = _tcschr (p, TEXT('\\'));
if (p) {
// Make p point to \0001\Software\subkey
p = _tcschr (_tcsinc (p), TEXT('\\'));
if (p) {
// Make p point to \Software\subkey
p = _tcschr (_tcsinc (p), TEXT('\\'));
if (p) {
// Make p point to \subkey
p = _tcschr (_tcsinc (p), TEXT('\\'));
if (p) {
// Make p point to subkey
p = _tcsinc (p);
} else {
p = S_EMPTY;
}
}
}
}
if (!p) {
DEBUGMSG ((
DBG_ERROR,
"pHwSoftwareDefaultDetectFilter: Not a hardware profile key: %s",
ObStr
));
return FILTER_RETURN_FAIL;
}
//
// If an entry exists in memdb's HKCC category, we have a
// suppression match
//
wsprintf (Node, TEXT("HKCC\\Software\\%s"), p);
if(MemDbGetValue(Node, NULL)) {
return FILTER_RETURN_CONTINUE;
}
wsprintf (Node, TEXT("HKCCS\\%s"), p);
if(HtFindString(g_SoftwareDefaultListHash, Node)){
return FILTER_RETURN_CONTINUE;
}
DEBUGMSG((DBG_VERBOSE, "pHwSoftwareDefaultDetectFilter(%s): not-default profile", Node));
*notDefault = TRUE;
return FILTER_RETURN_FAIL;
}
return FILTER_RETURN_CONTINUE;
}
BOOL
pIsSoftwareBranchDefault(
IN DWORD ConfigNumber
)
{
BOOL b;
DATAOBJECT Win9xOb;
TCHAR keyName[MAX_TCHAR_PATH];
BOOL notDefault;
wsprintf(keyName, S_9X_CONFIG_MASK S_SOFTWARE S_TREE, ConfigNumber);
b = CreateObjectStruct(keyName, &Win9xOb, WIN95OBJECT);
MYASSERT(b);
if(!b){
return TRUE;
}
notDefault = FALSE;
CopyObject(&Win9xOb,
NULL,
pHwSoftwareDefaultDetectFilter,
(PVOID)&notDefault);
FreeObjectStruct(&Win9xOb);
return !notDefault;
}
FILTERRETURN
pHwProfileEnumFilter (
IN CPDATAOBJECT SrcObjectPtr,
IN CPDATAOBJECT Unused, OPTIONAL
IN FILTERTYPE FilterType,
IN LPVOID FilterArg OPTIONAL
)
{
LPCTSTR p;
DWORD CurrentConfig = (DWORD)FilterArg;
HARDWARE_PROFILE hardwareProfile;
MYASSERT(CurrentConfig);
if (FilterType == FILTER_KEY_ENUM) {
// Make p point to 0001\Subkey
p = _tcschr (SrcObjectPtr->KeyPtr->KeyString, TEXT('\\'));
if (!p) {
// Object string is premature -- keep enumerating
return FILTER_RETURN_CONTINUE;
} else {
p = _tcsinc (p);
}
// Get current configuration number
hardwareProfile.NumberOnWin9x = _ttoi (p);
MYASSERT(hardwareProfile.NumberOnWin9x);
if(hardwareProfile.NumberOnWin9x == CurrentConfig){
if(GrowListGetSize(&g_HardwareProfileList)){
GrowListInsert(&g_HardwareProfileList, 0, (PBYTE)&hardwareProfile, sizeof(hardwareProfile));
}
else{
GrowListAppend(&g_HardwareProfileList, (PBYTE)&hardwareProfile, sizeof(hardwareProfile));
}
}
else if(!pIsSoftwareBranchDefault(hardwareProfile.NumberOnWin9x)){
GrowListAppend(&g_HardwareProfileList, (PBYTE)&hardwareProfile, sizeof(hardwareProfile));
}
}
return FILTER_RETURN_HANDLED;
}
/*
<EFBFBD> The current hardware profile is used as the "default" hardware
profile. The Windows NT key Hardware Profiles\0001 is renamed
to Hardware Profiles\Default for temporary use.
<EFBFBD> The Windows NT defaults are used as the base of all upgraded profiles.
For each hardware profile on Windows 9x, a Hardware Profiles\<n> key
is created, where <n> is the numeric identifier of the Windows 9x
hardware profile. All values and subkeys of Hardware Profiles\Default
are copied to this new key.
<EFBFBD> The Windows 9x settings are copied to NT. For each hardware profile
on Windows 9x, the entire registry tree in Config\<n> is copied to
Hardware Profiles\<n>, where <n> is the four-digit hardware profile
numeric identifier.
<EFBFBD> The default settings are deleted. Setup removes the Hardware
Profiles\Default key.
*/
BOOL
pCreateDefaultKey (
LPCTSTR BaseRegStr
)
{
DATAOBJECT SrcOb, DestOb;
TCHAR SrcObStr[MAX_ENCODED_RULE];
TCHAR DestObStr[MAX_ENCODED_RULE];
BOOL b;
wsprintf (SrcObStr, TEXT("%s\\%s\\*") , BaseRegStr, S_HW_ID_0001);
b = CreateObjectStruct (SrcObStr, &SrcOb, WINNTOBJECT);
MYASSERT(b);
wsprintf (DestObStr, TEXT("%s\\%s\\*"), BaseRegStr, S_HW_DEFAULT);
b = CreateObjectStruct (DestObStr, &DestOb, WINNTOBJECT);
MYASSERT(b);
b = RenameDataObject (&SrcOb, &DestOb);
FreeObjectStruct (&SrcOb);
FreeObjectStruct (&DestOb);
if (!b) {
LOG ((LOG_ERROR, "CreateDefaultKey: Could not rename %s to %s", SrcObStr, DestObStr));
}
return b;
}
VOID
pDeleteProfilesConfigValues(
IN DWORD ConfigNumber
)
{
DATAOBJECT Object;
TCHAR ObStr[MAX_ENCODED_RULE];
BOOL bResult;
UINT i;
static PCTSTR ObjectsValue[] = {
TEXT("Aliasable"),
TEXT("Cloned"),
TEXT("HwProfileGuid")
};
for(i = 0; i < ARRAYSIZE(ObjectsValue); i++){
wsprintf (ObStr, S_NT_HW_ID_MASK TEXT("\\[%s]"), ConfigNumber, ObjectsValue[i]);
bResult = CreateObjectStruct (ObStr, &Object, WINNTOBJECT);
if(!bResult){
MYASSERT(FALSE);
continue;
}
bResult = DeleteDataObjectValue (&Object);
MYASSERT(bResult);
FreeObjectStruct (&Object);
}
return;
}
BOOL
pDeleteDefaultKey (
IN LPCTSTR BaseRegStr
)
{
DATAOBJECT Object;
TCHAR ObStr[MAX_ENCODED_RULE];
BOOL b;
wsprintf (ObStr, TEXT("%s\\%s\\*"), BaseRegStr, S_HW_DEFAULT);
b = CreateObjectStruct (ObStr, &Object, WINNTOBJECT);
MYASSERT(b);
b = DeleteDataObject (&Object);
FreeObjectStruct (&Object);
if (!b) {
LOG ((LOG_ERROR, "CreateDefaultKey: Could not delete %s", ObStr));
}
return b;
}
BOOL
pCopyHwProfileConfigData (
IN DWORD ProfileSrcId,
IN DWORD ProfileDestId
)
{
DATAOBJECT DefaultOb, SrcConfigOb, DestOb;
BOOL b;
TCHAR Buf[MAX_TCHAR_PATH];
ZeroMemory (&DefaultOb, sizeof (DefaultOb));
ZeroMemory (&SrcConfigOb, sizeof (SrcConfigOb));
ZeroMemory (&DestOb, sizeof (DestOb));
//
// DefaultOb struct points to the default NT hardware profile
// configuration (i.e. HKLM\System\CCS\Hardware Profiles\Default)
//
b = CreateObjectStruct (S_NT_DEFAULT_HW_KEY S_TREE, &DefaultOb, WINNTOBJECT);
MYASSERT(b);
//
// SrcConfigOb struct points to the reg key holding the Win9x
// configuration settings (i.e. HKLM\Config\<ProfileId>)
//
wsprintf (Buf, S_9X_CONFIG_MASK S_TREE, ProfileSrcId);
b = b && CreateObjectStruct (Buf, &SrcConfigOb, WIN95OBJECT);
MYASSERT(b);
//
// DestOb struct points to the reg key to receive combined WinNT
// and Win9x settings (i.e. HKLM\System\CCS\Hardware Profiles\<n>)
//
wsprintf (Buf, S_NT_CONFIG_MASK S_TREE, ProfileDestId);
b = b && CreateObjectStruct (Buf, &DestOb, WINNTOBJECT);
MYASSERT(b);
//
// Copy defaults to new profile, then copy Win9x settings as well
//
if (b) {
b = FILTER_RETURN_FAIL != CopyObject (&DefaultOb, &DestOb, NULL, NULL);
if (!b) {
LOG ((LOG_ERROR, "pCopyHwProfileConfigData: Unable to copy defaults"));
}
}
if (b) {
b = FILTER_RETURN_FAIL != CopyObject (&SrcConfigOb, &DestOb,
pHwProfileSuppressFilter, NULL);
if (!b) {
LOG ((LOG_ERROR, "Copy Hardware Profile: Unable to copy Win9x settings"));
}
}
//
// Cleanup
//
FreeObjectStruct (&DefaultOb);
FreeObjectStruct (&SrcConfigOb);
FreeObjectStruct (&DestOb);
return b;
}
BOOL
pCopyHwProfileProperties (
IN DWORD ProfileSrcId,
IN DWORD ProfileDestId
)
{
DATAOBJECT DefaultOb, NameOb, DestOb;
BOOL b;
TCHAR Buf[MAX_TCHAR_PATH];
ZeroMemory (&DefaultOb, sizeof (DefaultOb));
ZeroMemory (&NameOb, sizeof (NameOb));
ZeroMemory (&DestOb, sizeof (DestOb));
//
// DefaultOb struct points to the default NT hardware profile
// properties
//
b = CreateObjectStruct (S_NT_DEFAULT_HW_ID_KEY S_TREE, &DefaultOb, WINNTOBJECT);
MYASSERT(b);
//
// NameOb struct points to the reg key holding FriendlyName<n>
// (i.e. HKLM\System\CCS\Control\IDConfigDB)
//
b = b && CreateObjectStruct (S_BASE_IDCONFIGDB_KEY, &NameOb, WIN95OBJECT);
MYASSERT(b);
//
// DestOb struct points to the reg key to receive FriendlyName
// and PreferenceOrder (i.e. HKLM\System\CCS\Control\IDConfigDB\Hardware
// Profiles\<ProfileId>)
//
wsprintf (Buf, S_NT_HW_ID_MASK S_TREE, ProfileDestId);
b = b && CreateObjectStruct (Buf, &DestOb, WINNTOBJECT);
MYASSERT(b);
//
// Copy default settings to dest object
//
if (b) {
b = FILTER_RETURN_FAIL != CopyObject (&DefaultOb, &DestOb, NULL, NULL);
if (!b) {
LOG ((LOG_ERROR, "Object copy failed"));
}
DEBUGMSG_IF ((!b, DBG_ERROR, "pCopyHwProfileProperties: Cannot copy, source=%s", DebugEncoder (&DefaultOb)));
DEBUGMSG_IF ((!b, DBG_ERROR, "pCopyHwProfileProperties: Cannot copy, dest=%s", DebugEncoder (&DestOb)));
}
//
// Copy FriendlyName and PreferenceOrder values to dest object
//
// Obtain FriendlyName<n>
if (b) {
wsprintf (Buf, S_FRIENDLYNAME_SPRINTF, ProfileSrcId);
SetRegistryValueName (&NameOb, Buf);
b = ReadObject (&NameOb);
if (!b) {
LOG ((LOG_ERROR, "Copy Hardware Profile Properties: Cannot obtain friendly name"));
}
}
// Copy data to dest object struct
if (b) {
SetRegistryType (&DestOb, REG_SZ);
b = ReplaceValue (&DestOb, NameOb.Value.Buffer, NameOb.Value.Size);
if (!b) {
LOG ((LOG_ERROR, "Copy Hardware Profile Properites: Cannot replace value data"));
}
}
// Write dest object
if (b) {
SetRegistryValueName (&DestOb, S_FRIENDLYNAME);
b = WriteObject (&DestOb);
if (!b) {
LOG ((LOG_ERROR, "Copy Hardware Profile Properties: Cannot write object"));
}
DEBUGMSG_IF ((!b, DBG_ERROR, "pCopyHwProfileProperties: Cannot write %s", DebugEncoder (&DestOb)));
}
// Set preference order in dest object struct
if (b) {
SetRegistryType (&DestOb, REG_DWORD);
ProfileDestId--;
b = ReplaceValue (&DestOb, (LPBYTE) &ProfileDestId, sizeof(ProfileDestId));
if (!b) {
LOG ((LOG_ERROR, "Copy Hardware Profile Properties: Cannot set preference order value data"));
}
DEBUGMSG_IF ((!b, DBG_ERROR, "pCopyHwProfileProperties: Cannot set preference order value data"));
}
// Write dest object
if (b) {
SetRegistryValueName (&DestOb, S_PREFERENCEORDER);
b = WriteObject (&DestOb);
if (!b) {
LOG ((LOG_ERROR, "Copy Hardware Profile Properties: Cannot write object"));
}
DEBUGMSG_IF ((!b, DBG_ERROR, "pCopyHwProfileProperties: Cannot write %s", DebugEncoder (&DestOb)));
}
//
// Cleanup
//
FreeObjectStruct (&DefaultOb);
FreeObjectStruct (&NameOb);
FreeObjectStruct (&DestOb);
return b;
}
DWORD
pGetCurrentConfig (
VOID
)
{
DATAOBJECT SrcOb;
BOOL b;
DWORD dwCurrentConfig = 1;
b = CreateObjectStruct (S_CURRENT_CONFIG, &SrcOb, WIN95OBJECT);
MYASSERT(b);
if (ReadObject (&SrcOb)) {
if (IsRegistryTypeSpecified (&SrcOb) && SrcOb.Type == REG_SZ) {
//
// Set destination's object to a REG_DWORD equivalent of
// the Win9x REG_SZ setting
//
dwCurrentConfig = _ttoi ((LPCTSTR) SrcOb.Value.Buffer);
if(!dwCurrentConfig){
dwCurrentConfig = 1;
MYASSERT(FALSE);
}
DEBUGMSG ((DBG_VERBOSE, "pGetCurrentConfig: %d", dwCurrentConfig));
}
else {
LOG ((
LOG_ERROR,
"Get Current Config: Read unexpected data type from registry in object"
));
DEBUGMSG ((
DBG_ERROR,
"pGetCurrentConfig: Read unexpected data type from registry in %s",
DebugEncoder (&SrcOb)
));
}
}
else {
LOG ((
LOG_ERROR,
"Get Current Config: Could not read object"
));
DEBUGMSG ((
DBG_ERROR,
"pGetCurrentConfig: Could not read %s",
DebugEncoder (&SrcOb)
));
}
FreeObjectStruct (&SrcOb);
return dwCurrentConfig;
}
BOOL
pCopyCurrentConfig (
VOID
)
{
DATAOBJECT SrcOb, DestOb;
BOOL b;
DWORD d;
b = CreateObjectStruct (S_CURRENT_CONFIG, &SrcOb, WIN95OBJECT);
MYASSERT(b);
b = CreateObjectStruct (S_CURRENT_CONFIG, &DestOb, WINNTOBJECT);
MYASSERT(b);
b = ReadObject (&SrcOb);
if (b) {
if (IsRegistryTypeSpecified (&SrcOb) && SrcOb.Type == REG_SZ) {
//
// Set destination's object to a REG_DWORD equivalent of
// the Win9x REG_SZ setting
//
d = _ttoi ((LPCTSTR) SrcOb.Value.Buffer);
b = ReplaceValue (&DestOb, (LPBYTE) &d, sizeof(d));
if (b) {
SetRegistryType (&DestOb, REG_DWORD);
b = WriteObject (&DestOb);
if (!b) {
LOG ((
LOG_ERROR,
"Copy Current Config: Could not write object"
));
}
DEBUGMSG_IF ((
!b,
DBG_ERROR,
"pCopyCurrentConfig: Could not write %s",
DebugEncoder (&DestOb)
));
}
else {
LOG ((LOG_ERROR, "Copy Current Config: Unable to replace value"));
DEBUGMSG ((DBG_ERROR, "pCopyCurrentConfig: Unable to replace value"));
}
}
else {
LOG ((
LOG_ERROR,
"Copy Current Config: Read unexpected data type from registry in object"
));
DEBUGMSG ((
DBG_ERROR,
"pCopyCurrentConfig: Read unexpected data type from registry in %s",
DebugEncoder (&SrcOb)
));
}
}
else {
LOG ((
LOG_ERROR,
"Copy Current Config: Could not read object"
));
DEBUGMSG ((
DBG_ERROR,
"pCopyCurrentConfig: Could not read %s",
DebugEncoder (&SrcOb)
));
}
FreeObjectStruct (&SrcOb);
FreeObjectStruct (&DestOb);
return b;
}
VOID
pMigrateHardwareProfiles(
VOID
)
{
PHARDWARE_PROFILE hardwareProfile;
UINT destHWProfileNumber;
UINT itemCount;
BOOL b;
for(destHWProfileNumber = 1, itemCount = GrowListGetSize(&g_HardwareProfileList);
destHWProfileNumber <= itemCount;
destHWProfileNumber++){
hardwareProfile = (PHARDWARE_PROFILE)GrowListGetItem(&g_HardwareProfileList, destHWProfileNumber - 1);
MYASSERT(hardwareProfile);
//
// Process hardware profile ID entry
//
b = pCopyHwProfileProperties(hardwareProfile->NumberOnWin9x, destHWProfileNumber);
if (!b) {
LOG ((LOG_ERROR, "Unable to continue processing hardware profile %04u->%04u", hardwareProfile->NumberOnWin9x, destHWProfileNumber));
}
//
// Process hardware profile configuration entries
//
if (b) {
b = pCopyHwProfileConfigData(hardwareProfile->NumberOnWin9x, destHWProfileNumber);
if (!b) {
LOG ((LOG_ERROR, "Unable to complete processing hardware profile %04u->%04u", hardwareProfile->NumberOnWin9x, destHWProfileNumber));
}
}
if(1 != destHWProfileNumber){
pDeleteProfilesConfigValues(destHWProfileNumber);
}
}
FreeGrowList(&g_HardwareProfileList);
}