/*++ 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, ARRAYSIZE(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, ARRAYSIZE(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)¬Default); 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; } /* · 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. · The Windows NT defaults are used as the base of all upgraded profiles. For each hardware profile on Windows 9x, a Hardware Profiles\ key is created, where is the numeric identifier of the Windows 9x hardware profile. All values and subkeys of Hardware Profiles\Default are copied to this new key. · The Windows 9x settings are copied to NT. For each hardware profile on Windows 9x, the entire registry tree in Config\ is copied to Hardware Profiles\, where is the four-digit hardware profile numeric identifier. · 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\) // 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\) // 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 // (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\) // 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 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); }