windows-nt/Source/XPSP1/NT/base/ntsetup/win95upg/w95upg/sysmig/condmsg.c

1418 lines
36 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1997 Microsoft Corporation
Module Name:
condmsg.c
Abstract:
Win95upg.inf has a section named [Conditional Incompatibilities] where the
lines in the section have the following syntax:
%group%, %subgroup%, %object%, %msg% [,<function>[,<argument>]]
%group% - A predefined root group number
%subgroup% - A localized subgroup displayed in the UI
%object% - The file, directory or registry location in which the message
is associated with
%msg% - A localized message
<function> - A function that determines if the message should be added to the
incompatible report
<argument> - An optional string parameter that is passed to <function.>
The code below implements the functions that are used in Win95upg.inf.
Author:
Marc Whitten (marcw) 3-Apr-1997
Revision History:
marcw 21-Jan-1999 Stale Beta messages removed.
marcw 10-Sep-1997 OSR2 beta warning added.
jimschm 06-Jul-1997 Added "object" to everything
jimschm 25-Jun-1997 Protocols warning
jimschm 28-May-1997 Hardware Profile warning
marcw 25-Apr-1997 <argument> ability passed.
jimschm 08-Apr-1997 Generalized
--*/
#include "pch.h"
#include "sysmigp.h"
#include "hwcomp.h"
//
// Function type declaration
//
typedef BOOL (TEST_FUNCTION_PROTOTYPE)(PCTSTR Object,
PCTSTR GroupBase,
PCTSTR Description,
PCTSTR Argument
);
typedef TEST_FUNCTION_PROTOTYPE * TEST_FUNCTION;
//
// Array of supported functions
//
#define FUNCTION_LIST \
DECLARATION_MACRO(SysAgentExtension) \
DECLARATION_MACRO(ArePasswordProvidersPresent) \
DECLARATION_MACRO(DoesRegKeyExist) \
DECLARATION_MACRO(DoRegKeyValuesExist) \
DECLARATION_MACRO(IsWin95Osr2) \
DECLARATION_MACRO(IsMSNInstalled) \
DECLARATION_MACRO(IsRasServerEnabled) \
DECLARATION_MACRO(IsDefValueEqual) \
//
// Declare the function prototypes
//
#define DECLARATION_MACRO(x) BOOL x (PCTSTR Object, \
PCTSTR GroupBase, \
PCTSTR Description, \
PCTSTR Argument \
);
FUNCTION_LIST
#undef DECLARATION_MACRO
//
// Create a lookup array
//
typedef struct {
PCTSTR Name;
TEST_FUNCTION Proc;
} FUNCTION_LIST_ELEMENT,*PFUNCTION_LIST_ELEMENT;
#define DECLARATION_MACRO(x) {#x, x},
FUNCTION_LIST_ELEMENT g_TestFunctionList[] = {
FUNCTION_LIST /*,*/
{NULL, NULL}
};
#undef DECLARATION_MACRO
//
// Function to locate Proc given a string
//
TEST_FUNCTION
pFindTestFunction (
IN PCTSTR FunctionStr
)
/*++
Routine Description:
pFindTestFunction searches the test function table declared above for
a specified function name and returns a pointer to the actual function
or NULL if the function does not exist.
Arguments:
FunctionStr - Specifies the name of function to find.
Return Value:
A pointer to the corresponding code, or NULL if the function does not exist.
--*/
{
INT Index;
for (Index = 0 ; g_TestFunctionList[Index].Name ; Index++) {
if (StringIMatch (g_TestFunctionList[Index].Name, FunctionStr)) {
return g_TestFunctionList[Index].Proc;
}
}
DEBUGMSG ((DBG_ERROR,"SysMig: %s is not a valid test function.", FunctionStr));
return NULL;
}
PTSTR
pGetFieldUsingPool (
IN OUT POOLHANDLE Pool,
IN INFCONTEXT *pic,
IN INT Field
)
/*++
Routine Description:
This function retrieves a string field using the Setup APIs but uses
PoolMem for allocation.
Arguments:
Pool - Specifies a handle to a valid pool (from PoolMemInitPool). Memory
is allocated from this pool.
pic - Specifies the INF section and line being queried.
Field - Specifies the field to retrieve.
Return Value:
A pointer to the field text, allocated in Pool, or NULL if the field was
not found or an error is encountered.
--*/
{
DWORD SizeNeeded;
PTSTR String;
if (!SetupGetStringField (pic, Field, NULL, 0, &SizeNeeded)) {
DEBUGMSG ((DBG_ERROR, "SysMig: SetupGetStringField failed for field %u.", Field));
return NULL;
}
String = PoolMemCreateString (Pool, SizeNeeded);
if (!SetupGetStringField (pic, Field, String, SizeNeeded, NULL)) {
DEBUGMSG ((DBG_ERROR,"SysMig: SetupGetStringField failed for field %u.", Field));
return NULL;
}
return String;
}
PCTSTR
pTranslateGroupString (
IN POOLHANDLE AllocPool,
IN UINT GroupId
)
/*++
Routine Description:
pTranslateGroupString converts a standard group number (1-based) into a
message ID, then loads the string resource. The group string is then
copied into the specified pool.
In win95upg.txt, the list is defined as:
1 - Hardware That Does Not Support Windows NT 5.0
2 - General Information
3 - Settings That Will Not Be Upgraded
4 - Software That Does Not Support Windows NT 5.0
5 - Software That Will Require Reinstallation
6 - Software with Minor Incompatibilities
7 - Software to Be Uninstalled by Setup
8 - Upgrade Pack Information
Arguments:
AllocPool - Specifies the pool to allocate the return string from
GroupId - Specifies a one-based ID that identifies the group. The
definition of the ID is hard-coded here.
Return Value:
A pointer to the string, or NULL if an invalid group was specified.
--*/
{
PCTSTR ResStr;
PCTSTR ResSubStr;
PTSTR ReturnStr = NULL;
UINT SubGroupId = 0;
switch (GroupId) {
case 0:
GroupId = MSG_BLOCKING_ITEMS_ROOT;
break;
case 1:
GroupId = MSG_INCOMPATIBLE_HARDWARE_ROOT;
break;
case 2:
GroupId = MSG_INSTALL_NOTES_ROOT;
break;
case 3:
GroupId = MSG_LOSTSETTINGS_ROOT;
break;
case 4:
GroupId = MSG_INCOMPATIBLE_ROOT;
SubGroupId = MSG_INCOMPATIBLE_DETAIL_SUBGROUP;
break;
case 5:
GroupId = MSG_REINSTALL_ROOT;
SubGroupId = MSG_REINSTALL_DETAIL_SUBGROUP;
break;
case 6:
GroupId = MSG_MINOR_PROBLEM_ROOT;
break;
case 7:
GroupId = MSG_INCOMPATIBLE_ROOT;
SubGroupId = MSG_AUTO_UNINSTALL_SUBGROUP;
break;
case 8:
GroupId = MSG_MIGDLL_ROOT;
break;
default:
return NULL;
}
ResStr = GetStringResource (GroupId);
if (ResStr) {
if (SubGroupId) {
ResSubStr = GetStringResource (SubGroupId);
if (ResSubStr) {
//
// We count the nul twice, assuming the nul is the same
// size as a backslash.
//
ReturnStr = PoolMemGetAlignedMemory (
AllocPool,
SizeOfString (ResStr) + SizeOfString (ResSubStr)
);
wsprintf (ReturnStr, TEXT("%s\\%s"), ResStr, ResSubStr);
FreeStringResource (ResSubStr);
}
} else {
ReturnStr = PoolMemDuplicateString (AllocPool, ResStr);
}
FreeStringResource (ResStr);
}
return ReturnStr;
}
VOID
pConditionalIncompatibilities (
VOID
)
/*++
Routine Description:
Processes the Conditional Incompatibilities section of WIN95UPG.INF, and does
other conditional incompatibility processing. Incompatibilities are added
via the API in w95upg\ui.
Arguments:
none
Return Value:
none
--*/
{
INFCONTEXT context;
POOLHANDLE aPool;
PTSTR descriptionString;
PTSTR functionString;
PTSTR argumentString;
TCHAR buffer[32];
static INT msgId = 0;
PCTSTR objectString;
PTSTR completeString;
TEST_FUNCTION Proc;
PCTSTR SubGroupString;
PCTSTR GroupString;
UINT GroupId;
BOOL fr;
BOOL negate;
aPool = PoolMemInitNamedPool ("Conditional Incompatibilities");
if (aPool) {
if (SetupFindFirstLine (
g_Win95UpgInf,
S_CONDITIONAL_INCOMPATIBILITIES,
NULL,
&context
)
) {
//
// Load in the standard group name
//
do {
//
// Get the group number
//
GroupString = pGetFieldUsingPool (aPool, &context, 1);
if (!GroupString) {
continue;
}
GroupId = _tcstoul (GroupString, NULL, 10);
GroupString = pTranslateGroupString (aPool, GroupId);
if (!GroupString) {
DEBUGMSG ((DBG_WHOOPS, "Invalid group ID: %u", GroupId));
continue;
}
//
// Get the subgroup string
//
SubGroupString = pGetFieldUsingPool (aPool, &context, 2);
if (!SubGroupString) {
DEBUGMSG ((DBG_WHOOPS, "Field 2 required in conditional message lines"));
continue;
}
if (*SubGroupString) {
completeString = (PTSTR) PoolMemGetMemory (
aPool,
SizeOfString (GroupString) +
SizeOfString (SubGroupString) +
2 * sizeof (TCHAR)
);
StringCopy (completeString, GroupString);
StringCopy (AppendWack (completeString), SubGroupString);
} else {
completeString = (PTSTR) GroupString;
}
//
// Get the object string
//
objectString = pGetFieldUsingPool (aPool, &context, 3);
if (!objectString) {
DEBUGMSG ((DBG_WHOOPS, "Field 3 required in conditional message lines"));
continue;
}
//
// Get the description
//
descriptionString = pGetFieldUsingPool (aPool, &context, 4);
if (!descriptionString) {
DEBUGMSG ((DBG_WHOOPS, "Field 4 required in conditional message lines"));
continue;
}
//
// If the field count is greater than two, there is a
// function string..
//
if (SetupGetFieldCount (&context) > 4) {
argumentString = NULL;
//
// Read in the functionString..
//
functionString = pGetFieldUsingPool (aPool, &context, 5);
if (!functionString) {
continue;
}
negate = *functionString == TEXT('!');
if (negate) {
functionString++;
}
if (SetupGetFieldCount(&context) > 5) {
//
// Read in the argument string.
//
argumentString = pGetFieldUsingPool(aPool,&context, 6);
}
//
// Find the function to call..
//
Proc = pFindTestFunction (functionString);
if (!Proc) {
continue;
}
fr = Proc (objectString, completeString, descriptionString,argumentString);
if (!negate && !fr || negate && fr) {
continue;
}
}
if (!objectString[0]) {
DEBUGMSG ((DBG_WARNING, "Manufacturing an object for %s message", completeString));
objectString = buffer;
msgId++;
wsprintf (buffer, "msg%u", msgId);
}
MsgMgr_ObjectMsg_Add (objectString, completeString, descriptionString);
} while (SetupFindNextLine (&context,&context));
}
else {
DEBUGMSG ((DBG_VERBOSE,"SysMig: %s not found in win95upg.inf.", S_CONDITIONAL_INCOMPATIBILITIES));
}
}
PoolMemDestroyPool(aPool);
}
DWORD
ConditionalIncompatibilities (
IN DWORD Request
)
{
switch (Request) {
case REQUEST_QUERYTICKS:
return TICKS_CONDITIONAL_INCOMPATIBILITIES;
case REQUEST_RUN:
pConditionalIncompatibilities ();
return ERROR_SUCCESS;
default:
DEBUGMSG ((DBG_ERROR, "Bad parameter in ConditionalIncompatibilities"));
}
return 0;
}
BOOL
pIsDefaultSystemAgent (
PCTSTR SageSubKey
)
{
INFCONTEXT context;
if (SetupFindFirstLine (
g_Win95UpgInf,
S_SAGE_EXCLUSIONS,
SageSubKey,
&context
)) {
return TRUE;
}
return FALSE;
}
BOOL
SysAgentExtension (
IN PCTSTR Object,
IN PCTSTR GroupBase,
IN PCTSTR Description,
IN PCTSTR Argument
)
/*++
Routine Description:
Produces conditional incompatibilities based on the presense of the
system agent extension, which is part of the Win95 plus pack but
not supported by NT.
Arguments:
Object - Unused
GroupBase - A WIN95UPG.INF-specified group name that is used
as the base of the message. The actual group name
stored in the registry is appended for the UI.
Description - A WIN95UPG.INF-specified description
Argument - Unused
Return Value:
FALSE, because we add the incompatibility message ourself.
Comments:
SAGE-aware programs declare themselves as such by creating a key in
HKLM\Software\Microsoft\Plus!\System Agent\SAGE. The name of the key
can be anything the program wants, but it should contain the following
values:
Program= Name of the program's .EXE file. This must be the same
.EXE name under which the program's PerApp path is
registered. You may append a command line parameter
indicating unattended operation (see Settings=,
below).
Friendly Name= Display name that System Agent will use in populating
the drop-down list in its "Schedule a program" dialog
box.
Settings= 1-bit binary field indicating whether program has a
Settings dialog box. If "Settings = "Settings = 0",
but the application supports an interactive mode, then
the "Program=" value should contain a command-line
parameter that tells your program it's being run by
SAGE, so that it knows to run in an unattended
fashion, for example, "DRVSPACE.EXE /noprompt" or
"MyApp.EXE /SAGERUN".
Result Codes Optional key containing a set of value pairs mapping
an exit code to a string describing the meaning of
that exit code. For example, for SCANDSKW, the
Result Codes key may contain a value such as:
0="ScanDisk completed successfully; no errors were
found." This is to allow SAGE to keep a
human-comprehensible log of the results of the
programs it runs. In addition to the value pairs,
this key should also contain a String value named
"Success", which indicates the highest value for an
exit code that designates that the program completed
successfully. The value names should be string
values, specified in decimal; the allowable range is
0<EFBFBD>32767.
--*/
{
REGKEY_ENUM e;
PCTSTR Data;
PCTSTR Module;
TCHAR FullKey[MAX_REGISTRY_KEY];
PCTSTR Group;
PCTSTR FullPathKeyStr;
PCTSTR FullPath;
HKEY ExtensionKey;
HKEY AppPathsKey;
//
// Scan HKLM\Software\Microsoft\Plus!\System Agent\SAGE for
// subkeys, then throw messages out for each friendly name.
//
if (EnumFirstRegKeyStr (&e, S_SAGE)) {
do {
ExtensionKey = OpenRegKey (e.KeyHandle, e.SubKeyName);
if (ExtensionKey) {
Data = GetRegValueData (ExtensionKey, S_SAGE_FRIENDLY_NAME);
if (Data && *Data) {
// Create full object string
wsprintf (FullKey, TEXT("%s\\%s"), S_SAGE, e.SubKeyName);
// Test win95upg.inf to see if this is a standard agent
if (!pIsDefaultSystemAgent (e.SubKeyName)) {
// Generate group string
Group = JoinPaths (GroupBase, Data);
// Get the full path for this EXE
FullPath = NULL;
Module = GetRegValueData (ExtensionKey, S_SAGE_PROGRAM);
if (Module && *Module) {
FullPathKeyStr = JoinPaths (S_SKEY_APP_PATHS, Module);
AppPathsKey = OpenRegKeyStr (FullPathKeyStr);
if (AppPathsKey) {
FullPath = GetRegValueData (AppPathsKey, S_EMPTY);
if (!(*FullPath)) {
MemFree (g_hHeap, 0, FullPath);
FullPath = NULL;
}
CloseRegKey (AppPathsKey);
}
FreePathString (FullPathKeyStr);
MemFree (g_hHeap, 0, Module);
}
// Add message
if ((!FullPath) || (!IsFileMarkedForAnnounce (FullPath))) {
MsgMgr_ObjectMsg_Add (FullPath?FullPath:FullKey, Group, Description);
}
// Cleanup
FreePathString (Group);
if (FullPath) {
MemFree (g_hHeap, 0 , FullPath);
FullPath = NULL;
}
}
MemFree (g_hHeap, 0, Data);
}
CloseRegKey (ExtensionKey);
}
} while (EnumNextRegKey (&e));
}
return FALSE; // pretend like it's not installed
}
BOOL
DoesRegKeyExist (
IN PCTSTR Object,
IN PCTSTR GroupBase,
IN PCTSTR Description,
IN PCTSTR Argument
)
/*++
Routine Description:
Returns TRUE if the registry key specified in Argument exists,
forcing an incompatibility message to be generated.
Arguments:
Object - Specifies the registry key to examine
GroupBase - A WIN95UPG.INF-specified group name
Description - A WIN95UPG.INF-specified description
Argument - Unused
Return Value:
TRUE if the registry key exists, or FALSE if it is not. TRUE
forces the message to be added to the report.
--*/
{
BOOL rKeyExists = FALSE;
HKEY key = NULL;
if (Object) {
key = OpenRegKeyStr (Object);
}
if (key) {
rKeyExists = TRUE;
CloseRegKey (key);
}
return rKeyExists;
}
BOOL
DoRegKeyValuesExist (
IN PCTSTR Object,
IN PCTSTR GroupBase,
IN PCTSTR Description,
IN PCTSTR Argument
)
/*++
Routine Description:
Returns TRUE if the registry key specified in Argument exists,
and has at least one named value, forcing an incompatibility
message to be generated.
Arguments:
Object - A WIN95UPG.INF-specified registry key
GroupBase - A WIN95UPG.INF-specified group name
Description - A WIN95UPG.INF-specified description
Argument - Unused
Return Value:
TRUE if the registry key exists, or FALSE if it is not. TRUE
forces the message to be added to the report.
--*/
{
BOOL ValuesExists = FALSE;
HKEY key = NULL;
REGVALUE_ENUM e;
if (Argument) {
key = OpenRegKeyStr (Argument);
}
if (key) {
if (EnumFirstRegValue (&e, key)) {
do {
if (e.ValueName[0]) {
ValuesExists = TRUE;
break;
}
} while (EnumNextRegValue (&e));
}
CloseRegKey (key);
}
return ValuesExists;
}
BOOL
IsWin95Osr2 (
IN PCTSTR Object,
IN PCTSTR GroupBase,
IN PCTSTR Description,
IN PCTSTR Argument
)
{
return ISWIN95_OSR2();
}
BOOL
IsMSNInstalled (
IN PCTSTR Object,
IN PCTSTR GroupBase,
IN PCTSTR Description,
IN PCTSTR Argument
)
{
HKEY key = NULL;
PCTSTR Data = NULL;
BOOL installed = FALSE;
if (Object) {
key = OpenRegKeyStr (Object);
}
if (key) {
Data = (PCTSTR) GetRegKeyData (key, S_EMPTY);
if (Data) {
if (DoesFileExist (Data)) {
installed = TRUE;
}
MemFree (g_hHeap, 0, Data);
}
CloseRegKey (key);
}
//
// Special cases
//
if (installed) {
//
// Win98 -- make sure setup GUID was deleted
//
key = OpenRegKeyStr (TEXT("HKLM\\Software\\Classes\\CLSID\\{4b876a40-11d1-811e-00c04fb98eec}"));
if (key) {
installed = FALSE;
CloseRegKey (key);
}
}
if (installed) {
//
// Win95 -- make sure SignUpDone flag is written
//
key = OpenRegKeyStr (TEXT("HKLM\\Software\\Microsoft\\MOS\\SoftwareInstalled"));
if (key) {
CloseRegKey (key);
} else {
installed = FALSE;
}
}
return installed;
}
BOOL
IsRasServerEnabled (
IN PCTSTR Object,
IN PCTSTR GroupBase,
IN PCTSTR Description,
IN PCTSTR Argument
)
{
BOOL rAddMessage = FALSE;
HKEY key;
PBYTE data;
if (!Object) {
return FALSE;
}
key = OpenRegKeyStr (Object);
if (key) {
data = GetRegValueData (key, TEXT("Enabled"));
if (data) {
if ((*(PDWORD)data) == 1) {
rAddMessage = TRUE;
}
MemFree (g_hHeap, 0, data);
}
CloseRegKey (key);
}
return rAddMessage;
}
BOOL
ArePasswordProvidersPresent (
IN PCTSTR Object,
IN PCTSTR GroupBase,
IN PCTSTR Description,
IN PCTSTR Argument
)
/*++
Routine Description:
Adds incompatibility messages for all password providers, excluding
password providers of known components such as the Microsoft
Networking Client or the Microsoft Client for NetWare.
Arguments:
Object - Unused
GroupBase - A WIN95UPG.INF-specified group name
Description - A WIN95UPG.INF-specified description
Argument - Unused
Return Value:
Always FALSE.
--*/
{
REGKEY_ENUM e;
PCTSTR data;
HKEY key;
INFCONTEXT ic;
TCHAR FullKey[MAX_REGISTRY_KEY];
PCTSTR FullGroup;
PCTSTR IncompatibleSoftware;
IncompatibleSoftware = GetStringResource (MSG_INCOMPATIBLE_ROOT);
if (!IncompatibleSoftware) {
return FALSE;
}
if (EnumFirstRegKeyStr (&e, S_PASSWORDPROVIDER)) {
do {
//
// See if this is a known password provider.
//
if (SetupFindFirstLine (
g_Win95UpgInf,
S_SUPPORTED_PASSWORD_PROVIDERS,
e.SubKeyName,
&ic
)) {
continue;
}
//
// This is an unsupported password provider key. Add a message.
//
key = OpenRegKey (e.KeyHandle, e.SubKeyName);
if (key) {
data = GetRegValueData (key, S_PASSWORDPROVIDER_DESCRIPTION);
if (data) {
wsprintf (FullKey, TEXT("%s\\%s"), S_PASSWORDPROVIDER, e.SubKeyName);
FullGroup = JoinPaths (IncompatibleSoftware, data);
MsgMgr_ObjectMsg_Add(
FullKey, // Object name
FullGroup, // Message title
Description // Message text
);
FreePathString (FullGroup);
MemFree (g_hHeap, 0, data);
}
CloseRegKey (key);
}
} while (EnumNextRegKey (&e));
}
FreeStringResource (IncompatibleSoftware);
//
// Since we build the message ourselves, just return FALSE. This will
// keep the ConditionalMessage function from adding this twice.
//
return FALSE;
}
BOOL
IsDefValueEqual (
IN PCTSTR Object,
IN PCTSTR GroupBase,
IN PCTSTR Description,
IN PCTSTR Argument
)
{
HKEY key = NULL;
PCTSTR Data = NULL;
BOOL equal = FALSE;
if (Object) {
key = OpenRegKeyStr (Object);
}
if (key) {
Data = (PCTSTR) GetRegKeyData (key, S_EMPTY);
if (Data) {
if (StringIMatch (Data, Argument)) {
equal = TRUE;
}
MemFree (g_hHeap, 0, Data);
}
CloseRegKey (key);
}
return equal;
}
VOID
pHardwareProfileWarning (
VOID
)
/*++
Routine Description:
Produces incompatibility messages for all hardware profiles that
have different hardware configurations. The upgrade cannot maintain
the list of disabled hardware in a hardware profile, so a warning
is generated.
Arguments:
none
Return Value:
none
--*/
{
REGKEY_ENUM e;
REGKEY_ENUM e2;
HKEY ProfileKey;
HKEY EnumKey;
HKEY ConfigDbKey;
DWORD Config;
TCHAR FriendlyName[MAX_PATH];
PCTSTR MsgGroup;
PCTSTR RootGroup;
PCTSTR HwProfiles;
PCTSTR Data;
TCHAR FullKey[MAX_REGISTRY_KEY];
UINT Profiles;
//
// How many hardware profiles? If just one, don't give a warning.
//
Profiles = 0;
if (EnumFirstRegKeyStr (&e, S_CONFIG_KEY)) {
do {
Profiles++;
} while (EnumNextRegKey (&e));
}
if (Profiles < 2) {
DEBUGMSG ((DBG_VERBOSE, "Hardware profiles: %u, suppressed all warnings", Profiles));
return;
}
//
// Enumerate the hardware profiles in HKLM\Config
//
if (EnumFirstRegKeyStr (&e, S_CONFIG_KEY)) {
do {
//
// Determine if profile has an Enum key
//
ProfileKey = OpenRegKey (e.KeyHandle, e.SubKeyName);
if (ProfileKey) {
EnumKey = OpenRegKey (ProfileKey, S_ENUM_SUBKEY);
if (EnumKey) {
//
// Determine if Enum key is empty
//
if (EnumFirstRegKey (&e2, EnumKey)) {
AbortRegKeyEnum (&e2);
//
// Obtain friendly name for config
//
ConfigDbKey = OpenRegKeyStr (S_FRIENDLYNAME_KEY);
if (ConfigDbKey) {
Config = _ttoi (e.SubKeyName);
wsprintf (FriendlyName, S_FRIENDLYNAME_SPRINTF, Config);
Data = GetRegValueData (ConfigDbKey, FriendlyName);
if (Data) {
//
// Put message in incompatibility report
//
wsprintf (FullKey, TEXT("%s\\%s"), S_CONFIG_KEY, e.SubKeyName);
//
// Generate Msg and MsgGroup
//
RootGroup = GetStringResource (MSG_INSTALL_NOTES_ROOT);
MYASSERT (RootGroup);
HwProfiles = GetStringResource (MSG_HWPROFILES_SUBGROUP);
MYASSERT (HwProfiles);
MsgGroup = JoinPaths (RootGroup, HwProfiles);
MYASSERT (MsgGroup);
FreeStringResource (RootGroup);
FreeStringResource (HwProfiles);
RootGroup = MsgGroup;
MsgGroup = JoinPaths (RootGroup, Data);
MYASSERT (MsgGroup);
FreePathString (RootGroup);
//
// Add the message and clean up
//
MsgMgr_ObjectMsg_Add (FullKey, MsgGroup, S_EMPTY);
FreePathString (MsgGroup);
MemFree (g_hHeap, 0, Data);
}
ELSE_DEBUGMSG ((DBG_ERROR, "Hardware profile lacks friendly name"));
CloseRegKey (ConfigDbKey);
}
ELSE_DEBUGMSG ((DBG_ERROR, "Hardware profile lacks config DB key"));
if (!ConfigDbKey) {
LOG ((LOG_ERROR, "Hardware profile lacks config DB key"));
}
}
CloseRegKey (EnumKey);
}
CloseRegKey (ProfileKey);
}
} while (EnumNextRegKey (&e));
}
}
DWORD
HardwareProfileWarning (
IN DWORD Request
)
{
switch (Request) {
case REQUEST_QUERYTICKS:
return TICKS_HARDWARE_PROFILE_WARNING;
case REQUEST_RUN:
pHardwareProfileWarning ();
return ERROR_SUCCESS;
default:
DEBUGMSG ((DBG_ERROR, "Bad parameter in HardwareProfileWarning"));
}
return 0;
}
VOID
pUnsupportedProtocolsWarning (
VOID
)
/*++
Routine Description:
Produces incompatibility messages for network protocols that
do not ship with equivalent versions on NT.
Arguments:
none
Return Value:
none
--*/
{
PCTSTR NetworkProtocols;
PCTSTR Message;
PCTSTR ArgArray[2];
REGKEY_ENUM e;
HKEY ProtocolKey, BindingKey, DriverKey;
REGKEY_ENUM ProtocolEnum;
INFCONTEXT ic;
PCTSTR Driver, DriverDesc, Mfg;
DWORD MsgId;
TCHAR DriverKeyStr[MAX_REGISTRY_KEY];
TCHAR FullKey[MAX_REGISTRY_KEY];
//
// Enumerate the HKLM\Enum\Network key
//
if (EnumFirstRegKeyStr (&e, S_ENUM_NETWORK_KEY)) {
do {
//
// Check win95upg.inf to see if the network protocol is known
//
if (SetupFindFirstLine (
g_Win95UpgInf,
S_SUPPORTED_PROTOCOLS,
e.SubKeyName,
&ic
)) {
// It is, skip to next protocol
continue;
}
//
// A warning message must be generated. We must take the first
// subkey of the protocol, query its Driver value, and look up
// the DriverDesc in HKLM\System\CCS\Services\Class\<driver>.
//
ProtocolKey = OpenRegKey (e.KeyHandle, e.SubKeyName);
if (ProtocolKey) {
if (EnumFirstRegKey (&ProtocolEnum, ProtocolKey)) {
BindingKey = OpenRegKey (ProtocolKey, ProtocolEnum.SubKeyName);
if (BindingKey) {
Driver = (PCTSTR) GetRegValueDataOfType (
BindingKey,
S_DRIVER,
REG_SZ
);
if (Driver) {
//
// We now know the driver... let's get the
// driver description.
//
wsprintf (DriverKeyStr, S_CLASS_KEY TEXT("\\%s"), Driver);
MemFree (g_hHeap, 0, Driver);
DriverKey = OpenRegKeyStr (DriverKeyStr);
if (DriverKey) {
DriverDesc = (PCTSTR) GetRegValueDataOfType (
DriverKey,
S_DRIVERDESC,
REG_SZ
);
if (DriverDesc) {
//
// Obtain the manufacturer for use in message.
// If the manufacturer is not known, display
// a generic message.
//
Mfg = (PCTSTR) GetRegValueDataOfType (
BindingKey,
S_MFG,
REG_SZ
);
if (!Mfg) {
MsgId = MSG_UNSUPPORTED_PROTOCOL;
} else {
MsgId = MSG_UNSUPPORTED_PROTOCOL_KNOWN_MFG;
}
ArgArray[0] = DriverDesc;
ArgArray[1] = Mfg;
NetworkProtocols = ParseMessageID (MSG_NETWORK_PROTOCOLS, ArgArray);
if(Mfg && StringIMatch(Mfg, TEXT("Microsoft"))){
Message = ParseMessageID (MSG_UNSUPPORTED_PROTOCOL_FROM_MICROSOFT, ArgArray);
}
else {
Message = ParseMessageID (MsgId, ArgArray);
}
MYASSERT (NetworkProtocols && Message);
wsprintf (FullKey, TEXT("%s\\%s"), S_ENUM_NETWORK_KEY, e.SubKeyName);
MsgMgr_ObjectMsg_Add (FullKey, NetworkProtocols, Message);
if (Mfg) {
MemFree (g_hHeap, 0, Mfg);
}
MemFree (g_hHeap, 0, DriverDesc);
}
}
CloseRegKey (DriverKey);
}
CloseRegKey (BindingKey);
}
}
CloseRegKey (ProtocolKey);
}
} while (EnumNextRegKey (&e));
}
}
DWORD
UnsupportedProtocolsWarning (
IN DWORD Request
)
{
switch (Request) {
case REQUEST_QUERYTICKS:
return TICKS_UNSUPPORTED_PROTOCOLS_WARNING;
case REQUEST_RUN:
pUnsupportedProtocolsWarning ();
return ERROR_SUCCESS;
default:
DEBUGMSG ((DBG_ERROR, "Bad parameter in UnsupportedProtocolWarning"));
}
return 0;
}